• 洛谷 P2331 最大子矩阵 题解


    题面

    对于m==1和m==2两种状态进行不同的dp;

    设sum[i][1]表示第一列的前缀和,sum[i][2]表示第二列的前缀和;

    sum[i][1]=sum[i-1][1]+a[i][1];

    sum[i][2]=sum[i-1][2]+a[i][2];

    当m=1时,

      设f[i][j]表示前i个数选择j个区间所得到的最大值;

       那么枚举0<=p<i, f[i][j]=max(f[i-1][j],f[p][j-1]+sum[i][1]-sum[p][1]);

        答案就是f[n][k];

    当m=2时,与上面的类似;

       f[i][j][p]表示第一列选择前i个数,第二列选择前j个数,总共选择p个矩阵的最大值;

       那么枚举0<=p<i,f[i][j][p]=max(f[i-1][j][p],f[i][j-1][p],f[i][j][p],f[l][j][p-1]+sum[i][1]-sum[l][1],f[i][l][p-1]+sum[j][2]-sum[l][2],f[l][l][p-1]+sum[i][2]+sum[i][1]-sum[l][2]-sum[l][1]);

       答案就是f[n][n][k];

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,K;
    int a[110][5];
    int sum[110][5];
    int g[110][110];
    void solve1()
    {
        for(int k=1;k<=K;k++){
            for(int i=1;i<=n;i++){
                g[i][k]=g[i-1][k];
                for(int j=0;j<i;j++){
                    g[i][k]=max(g[j][k-1]+sum[i][1]-sum[j][1],g[i][k]);
                }
            }
        }
        cout<<g[n][K];
    }
    int f[110][110][110];
    void solve2()
    {
        for(int k=1;k<=K;k++){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    f[i][j][k]=max(f[i-1][j][k],f[i][j-1][k]);
                    for(int l=0;l<i;l++){
                        f[i][j][k]=max(f[i][j][k],f[l][j][k-1]+sum[i][1]-sum[l][1]);
                    }
                    for(int l=0;l<j;l++){
                        f[i][j][k]=max(f[i][j][k],f[i][l][k-1]+sum[j][2]-sum[l][2]);
                    }
                    if(i==j){
                        for(int l=0;l<i;l++){
                            f[i][j][k]=max(f[i][j][k],f[l][l][k-1]+sum[i][2]+sum[i][1]-sum[l][2]-sum[l][1]);
                        }
                    }
                }
            }
        }
        cout<<f[n][n][K];
    }
    int main()
    {
        cin>>n>>m>>K;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cin>>a[i][j];        
            }
        }
        for(int i=1;i<=n;i++){
            sum[i][1]=sum[i-1][1]+a[i][1];
            sum[i][2]=sum[i-1][2]+a[i][2];
        }
        if(m==1){
            solve1();
        }
        else{
            solve2();
        }
    }
    /*
    3 1 2
    1
    -2
    2
    */
  • 相关阅读:
    linux下文本处理
    JSON对象的序列化和反序列化
    大整数相加的js实现
    前端日志格式化
    对象deepcopy
    基于vue实现的小程序管理后台图文编辑器
    原型和原型链
    函数声明、函数表达式及函数立即执行
    网址
    判断日期是否相等
  • 原文地址:https://www.cnblogs.com/kamimxr/p/11395584.html
Copyright © 2020-2023  润新知