zoukankan      html  css  js  c++  java
  • 洛谷 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
    */
  • 相关阅读:
    利用runtime检測这个对象是否存在某属性?
    Android Studio 使用 SVN 必然遇到问题:commit ** File out of data 问题解决方法
    JPA測试实例
    pat(A) 1063. Set Similarity(STL)
    @Override用在哪儿
    Highcharts数据表示(3)
    #pragma pack (n) 惹的祸
    C++二阶构造函数
    使用自定义的控件
    C++ explicit
  • 原文地址:https://www.cnblogs.com/kamimxr/p/11395584.html
Copyright © 2011-2022 走看看