• [SCOI2005] 最大子矩阵


    题目链接:https://ac.nowcoder.com/acm/problem/20242

    思路:
    因为m最大只有2,所以可以先算m==1的时候,就相当于求最大m子串和,状态转移方程为 :
    dp[i][k][0]=max(dp[i-1][k][0],dp[i-1][1][k]);
    dp[i][k][1]=max(dp[i-1][k][1],max(dp[i-1][k-1][1],dp[i-1][k-1][0]))+num[i];

    然后m==2的时候,用dp[i][j][k]来表示,第一列为1-i,第二列为1-j,k为选的k个矩形。 sum[n][1]表示第一列的前缀和,sum[n][2]表示第二列的前缀和。
    计算的时候,我们可以当做是分别计算第一列和第二列的最大m子串和,然后再把他们两列进行整合,因此可以分为四种情况:
    计算第一列的时候:
    dp[i][j][k]=max(dp[i][j][k],dp[t][j][k-1]+sum[i][1]-sum[t][1]);
    计算第二列的时候:
    dp[i][j][k]=max(dp[i][j][k],dp[i][t][k-1]+sum[j][2]-sum[t][2]);
    当i==j的时候,会有他们两列的子串重合为一个矩形的可能:
    dp[i][j][k]=max(dp[i][j][k],dp[t][t][k-1]+sum[i][1]-sum[t][1]+sum[j][2]-sum[t][2]);
    什么都不选的情况:
    dp[i][j][k]=max(dp[i-1][j][k],dp[i][j-1][k]);

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <stack>
    #include <queue>
    #include <cmath>
    #define ll long long
    #define pi 3.1415927
    #define inf 0x3f3f3f3f
    #define mod 1000000007
    using namespace std;
    int sum[105][5],dp[105][105][12],num[105][5];
    int main ()
    {
        
        int T,n,m,i,t,j,k,p;
        cin>>n>>m>>k;
        for(i=1;i<=n;++i)
            for(j=1;j<=m;++j){
                cin>>num[i][j];
                sum[i][j]=sum[i-1][j]+num[i][j]; //计算前缀和
            }
        
        if(m==1)
        {
            for(i=1;i<=n;++i)
                for(int kk=1;kk<=k;++kk){//m==1的时候,相当于求最大m子串和
                    dp[i][0][kk]=max(dp[i-1][0][kk],dp[i-1][1][kk]);
                    dp[i][1][kk]=max(dp[i-1][1][kk],max(dp[i-1][1][kk-1],dp[i-1][0][kk-1]))+num[i][1];
                }
            p=max(dp[n][1][k],dp[n][0][k]);
            cout<<p<<endl;
        }
        else 
        {
            for(i=1;i<=n;++i)
                for(j=1;j<=n;++j)
                    for(int kk=1;kk<=k;++kk)
                    {
                        dp[i][j][kk]=max(dp[i-1][j][kk],dp[i][j-1][kk]); //什么都不选的情况
                        for(t=0;t<i;++t)
                            dp[i][j][kk]=max(dp[i][j][kk],dp[t][j][kk-1]+sum[i][1]-sum[t][1]); //在第一列选区间
                        for(t=0;t<j;++t)
                            dp[i][j][kk]=max(dp[i][j][kk],dp[i][t][kk-1]+sum[j][2]-sum[t][2]); //在第二列选区间
                        if(i==j)
                            for(t=0;t<j;++t) //当i==j的时候,有可能出现区间相同的情况
                                dp[i][j][kk]=max(dp[i][j][kk],dp[t][t][kk-1]+sum[i][1]-sum[t][1]+sum[j][2]-sum[t][2]);
                    }
            cout<<dp[n][n][k]<<endl;
        }
        return 0;
    }
  • 相关阅读:
    ECharts
    JSON(及其在ajax前后端交互的过程)小识
    fullpage.js全屏滚动插件使用小结
    php json_encode数据格式化
    jQuery的DOM操作实例(3)——创建节点&&编写一个弹窗
    jQuery的DOM操作实例(2)——拖拽效果&&拓展插件
    jQuery的DOM操作实例(1)——选项卡&&Tab切换
    日常css技巧小结(2)-- inline-block带来的迷惑
    日常css技巧小结(1)--背景透明度改变对内容无影响
    浅析JavaScript事件流——冒泡
  • 原文地址:https://www.cnblogs.com/blowhail/p/13073295.html
Copyright © 2020-2023  润新知