题面这么简洁,清晰,易懂,真是不可多得的良心题面(比我上一篇博客那道题良心多了)
我们会发现m只有2
如果m是一个较大的数的话可能会麻烦一点,只有2的话就很好做了
我们先来考虑m为1的情况,很简单,\(f[i][j][0/1]\)表示是否选第i个,已经选了j个连续矩形,最大为多少,直接dp即可
那么如果m为2的话,有5种情况
\(f[i][j][k]\)表示第i行为第k种情况,有j个矩形,最大为多少
第一种:两个都不选,空出这一行
第二种:选左边,不选右边
第三种:选右边,不选左边
第四种:左右都选,但是不属于同一矩形
第五种:左右都选,属于同一矩形
分出这五种情况来,这道题就A了
下面放代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cctype>
#define ll long long
#define gc getchar
#define maxn 105
#define maxm 15
using namespace std;
inline ll read(){
ll a=0;int f=0;char p=gc();
while(!isdigit(p)){f|=p=='-';p=gc();}
while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
return f?-a:a;
}int n,m,k,a[maxn][maxn],f[maxn][maxm][5];
int main(){
n=read();m=read();k=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
a[i][j]=read();
if(m==1){
for(int i=1;i<=n;++i)
for(int j=1;j<=k;++j){
f[i][j][0]=max(f[i-1][j][1],f[i-1][j][0]);
f[i][j][1]=max(f[i-1][j][1],f[i-1][j-1][0])+a[i][1];
}
printf("%d\n",max(f[n][k][0],f[n][k][1]));
return 0;
}memset(f,~63,sizeof f);
for(int i=0;i<=n;++i)
for(int j=0;j<=k;++j)
f[i][j][0]=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=k;++j){
f[i][j][0]=max(f[i-1][j][0],max(max(f[i-1][j][1],f[i-1][j][2]),max(f[i-1][j][3],f[i-1][j][4])));
f[i][j][1]=max(f[i-1][j-1][0],max(max(f[i-1][j][1],f[i-1][j][3]),max(f[i-1][j-1][2],f[i-1][j-1][4])))+a[i][1];
f[i][j][2]=max(f[i-1][j-1][0],max(max(f[i-1][j][2],f[i-1][j][3]),max(f[i-1][j-1][1],f[i-1][j-1][4])))+a[i][2];
f[i][j][3]=max(max(f[i-1][j-1][1],f[i-1][j-1][2]),f[i-1][j][3]);
f[i][j][4]=max(f[i-1][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[i][1]+a[i][2];
if(j>=2)f[i][j][3]=max(f[i][j][3],max(f[i-1][j-2][0],f[i-1][j-2][4]));
f[i][j][3]+=a[i][1]+a[i][2];
}
printf("%d\n",max(f[n][k][0],max(max(f[n][k][1],f[n][k][2]),max(f[n][k][3],f[n][k][4]))));
return 0;
}