【Luogu】P2331最大子矩阵(DP)

  题目链接

  这题的状态转移方程真是粗鄙。

  f[i][j][k]表示前i行用了j个矩阵状态为k的时候的最大值。

  k=0:两列都不选。

  k=1:取左弃右。

  k=2:选右弃左。

  k=3:左右都选,但分属于两个独立矩阵。

  k=4:左右都选,且同属于一个矩阵。

  参考题解:孤寂的时代

  代码

#include<cstdio>
#include<cctype>
#include<cstring>

inline long long max(long long x,long long y){    return x>y?x:y;    }

inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

int f[103][12][6];
int que[1000][5];

int main(){
    int n=read(),m=read(),q=read();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)    que[i][j]=read();
    memset(f,0xaf,sizeof(f));
    for(int i=0;i<=n;++i)
        for(int j=0;j<=q;++j)    f[i][j][0]=0;
    for(int i=1;i<=n;++i){
        int a=que[i][1],b=que[i][2];
        for(int j=1;j<=q;++j){
            f[i][j][0]=max(max(f[i-1][j][0],f[i-1][j][1]),max(f[i-1][j][2],max(f[i-1][j][3],f[i-1][j][4])));
            f[i][j][1]=max(max(max(f[i-1][j-1][0],f[i-1][j][1]),max(f[i-1][j-1][2],f[i-1][j][3]))+a,f[i-1][j-1][4]+a);
            f[i][j][2]=max(max(max(f[i-1][j-1][0],f[i-1][j-1][1]),max(f[i-1][j][2],f[i-1][j][3]))+b,f[i-1][j-1][4]+b);
            f[i][j][3]=max(f[i-1][j-1][1],max(f[i-1][j-1][2],f[i-1][j][3]))+a+b;
            if(j>1)    f[i][j][3]=max(f[i][j][3],f[i-1][j-2][4]+a+b);
            f[i][j][4]=max( max(f[i-1][j-1][0],f[i-1][j-1][1]),max(f[i-1][j-1][2],f[i-1][j-1][3]))+a+b;
            f[i][j][4]=max(f[i][j][4],f[i-1][j][4]+a+b);
        }
    }
    int ans=f[n][q][1];
    if(ans<f[n][q][0])    ans=f[n][q][0];
    if(ans<f[n][q][2])    ans=f[n][q][2];
    if(ans<f[n][q][3])    ans=f[n][q][3];
    if(ans<f[n][q][4])    ans=f[n][q][4];
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/cellular-automaton/p/7609357.html