[SCOI2005]最大子矩阵

link

不难,挺基础的dp。考场上纠结能不能选用空子矩阵,然后纠结着纠结着有些东西就飘了,导致第一个sub里手抖死掉了。70分,好冤啊。

就很简单,考虑到给定的矩阵列数只有1或2。1的情况随便怎么动规都可以,2的情况要额外维护最后一行的状态方便转移(共5个状态),注意f的初值即可。但它似乎没卡空矩阵。

#include<bits/stdc++.h>
//#define feyn
const int N=110;
const int M=20;
using namespace std;
inline void read(int &wh){
	wh=0;int f=1;char w=getchar();
	while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
	while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
	wh*=f;return;
}
inline int max(int s1,int s2){
	return s1<s2?s2:s1;
}
inline void check(int &s1,int s2){
	s1=s1<s2?s2:s1;
}

int m,n,num,ans=-1e9,a[N][3],f[N][M][5];

signed main(){
	
	#ifdef feyn
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);read(n);read(num);
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++)read(a[i][j]);
	}
	if(n==1){
		memset(f,0xcf,sizeof(f));
		f[0][0][0]=0;
		for(int i=1;i<=m;i++){
			for(int j=num;j>=0;j--){
				f[i][j][0]=max(f[i-1][j][0],f[i-1][j][1]);
				f[i][j][1]=f[i-1][j][1]+a[i][1];
				if(j)check(f[i][j][1],max(f[i-1][j-1][1],f[i-1][j-1][0])+a[i][1]);
			}
			//printf("c:%d %d %d %d\n",f[i][0][0],f[i][0][1],f[i][1][0],f[i][1][1]);
		}
		printf("%d\n",max(f[m][num][0],f[m][num][1]));
		return 0;
	}
	memset(f,0xcf,sizeof(f));
	f[0][0][2]=0;
	for(int i=1;i<=m;i++){
		for(int j=0;j<=num;j++){
			check(f[i][j][0],f[i-1][j][0]);
			if(j)check(f[i][j][0],f[i-1][j-1][1]);
			if(j)check(f[i][j][0],f[i-1][j-1][2]);
			check(f[i][j][0],f[i-1][j][3]);
			if(j)check(f[i][j][0],f[i-1][j-1][4]);
			f[i][j][0]+=a[i][1];
			
			check(f[i][j][1],f[i-1][j][1]);
			if(j)check(f[i][j][1],f[i-1][j-1][0]);
			if(j)check(f[i][j][1],f[i-1][j-1][2]);
			check(f[i][j][1],f[i-1][j][3]);
			if(j)check(f[i][j][1],f[i-1][j-1][4]);
			f[i][j][1]+=a[i][2];
			
			for(int k=0;k<5;k++)check(f[i][j][2],f[i-1][j][k]);
			
			if(j)check(f[i][j][3],f[i-1][j-1][0]);
			if(j)check(f[i][j][3],f[i-1][j-1][1]);
			if(j>=2)check(f[i][j][3],f[i-1][j-2][2]);
			check(f[i][j][3],f[i-1][j][3]);
			if(j>=2)check(f[i][j][3],f[i-1][j-2][4]);
			f[i][j][3]+=a[i][1]+a[i][2];
			
			if(j)for(int k=0;k<4;k++)check(f[i][j][4],f[i-1][j-1][k]);
			check(f[i][j][4],f[i-1][j][4]);
			f[i][j][4]+=a[i][1]+a[i][2];
		}
	}
	for(int i=0;i<5;i++)check(ans,f[m][num][i]);
	printf("%d",ans);
	
	return 0;
}
posted @ 2022-07-05 14:18  Feyn618  阅读(14)  评论(0编辑  收藏  举报