BZOJ-1084: [SCOI2005]最大子矩阵

[文章目录]

Description

这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵不能相互重叠。1≤n≤100,1≤m≤2,1≤k≤10

发现m<=2,分情况dp即可。注意转移的时候,当前行和上一行满足作为同一个子矩阵时也可以当做新开了个矩阵。m=2的时候,存在着5种状态(两列为同一个矩阵)。dp[i][j][k]第i行,已有j个矩阵,当前边界状态为k的最大收益

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,k;
int dp1[110][12][2],mp1[110],mp2[110];
int dp[110][12][5];
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    if(m==1)
    {
        for(int i=1;i<=n;++i) scanf("%d",mp1+i);
        memset(dp1,0xef,sizeof dp1);
        for(int i=0;i<=n;++i) dp1[i][0][0]=0;
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=k;++j)
            {
                dp1[i][j][0]=max(dp1[i-1][j][0],dp1[i-1][j][1]);
                dp1[i][j][1]=max(max(dp1[i-1][j][1],dp1[i-1][j-1][1]),dp1[i-1][j-1][0])+mp1[i];
            }
        }
        printf("%d",max(dp1[n][k][0],dp1[n][k][1]));
    }
    else
    {
        for(int i=1;i<=n;++i) scanf("%d%d",mp1+i,mp2+i);
        memset(dp,0xef,sizeof dp);
        for(int i=0;i<=n;++i) dp[i][0][0]=0;
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=k;++j)
            {
                dp[i][j][0]=max(dp[i-1][j][0],max(dp[i-1][j][1],max(dp[i-1][j][2],max(dp[i-1][j][3],dp[i-1][j][4]))));
                dp[i][j][1]=max(dp[i-1][j-1][0],max(dp[i-1][j-1][1],max(dp[i-1][j][1],max(dp[i-1][j-1][2],
                    max(dp[i-1][j-1][3],max(dp[i-1][j][3],dp[i-1][j-1][4]))))))+mp2[i];
                dp[i][j][2]=max(dp[i-1][j-1][0],max(dp[i-1][j-1][1],max(dp[i-1][j][2],max(dp[i-1][j-1][2],
                    max(dp[i-1][j-1][3],max(dp[i-1][j][3],dp[i-1][j-1][4]))))))+mp1[i];
                if(j>1) dp[i][j][3]=max(dp[i-1][j-2][0],max(dp[i-1][j-2][1],max(dp[i-1][j-2][2],max(dp[i-1][j-2][3],dp[i-1][j-2][4]))))+mp1[i]+mp2[i];
                dp[i][j][3]=max(dp[i][j][3],max(dp[i-1][j-1][1],max(dp[i-1][j-1][2],max(dp[i-1][j-1][3],dp[i-1][j][3])))+mp1[i]+mp2[i]);
                dp[i][j][4]=max(dp[i-1][j-1][0],max(dp[i-1][j-1][1],max(dp[i-1][j-1][2],max(dp[i-1][j-1][3],max(dp[i-1][j-1][4],dp[i-1][j][4])))))+mp1[i]+mp2[i];
            }
        }
        printf("%d",max(dp[n][k][0],max(dp[n][k][1],max(dp[n][k][2],max(dp[n][k][3],dp[n][k][4])))));
    }
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注