bzoj 1084;vijos 1191 [SCOI2005] 最大子矩阵
Description
这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵不能相互重叠。
Input
第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767)。
Output
只有一行为k个子矩阵分值之和最大为多少。
Sample Input
3 2 2
1 -3
2 3
-2 3
1 -3
2 3
-2 3
Sample Output
9
直接拎dp
#include<cstdio> #include<algorithm> using namespace std; int n,m,o,p,k; int a[101][2]; int dp[101][11][5]; bool f; inline int read(){ p=0;o=getchar();f=1; while(o<'0'||o>'9'){if (o=='-') f=0;o=getchar();} while(o>='0'&&o<='9') p=p*10+o-48,o=getchar(); if (f)return p;else return -p; } inline int max(int a,int b){return a>b?a:b;} int main(){ register int i,j; n=read();m=read();k=read(); for (i=1;i<=n;i++) for (j=0;j<m;j++) a[i][j]=read(); if (m==1){ for (j=0;j<=k;j++) dp[0][j][0]=dp[0][j][1]=-1e9; dp[0][0][0]=0; for (i=1;i<=n;i++) for (j=1;j<=k;j++) dp[i][j][1]=max(dp[i-1][j][1],dp[i-1][j-1][0])+a[i][0],dp[i][j][0]=max(dp[i][j][1],dp[i-1][j][0]); printf("%d\n",dp[n][k][0]); }else{ for (j=0;j<=k;j++) dp[0][j][0]=dp[0][j][1]=dp[0][j][2]=dp[0][j][3]=dp[0][j][4]=-1e9; dp[0][0][0]=0; for (i=1;i<=n;i++) for (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][j-1][0],max(dp[i-1][j][4],dp[i-1][j][1]))+a[i][0], dp[i][j][2]=max(dp[i][j-1][0],max(dp[i-1][j][4],dp[i-1][j][2]))+a[i][1], dp[i][j][3]=max(dp[i][j-1][0],dp[i-1][j][3])+a[i][0]+a[i][1], dp[i][j][4]=j>=2?max(dp[i][j-2][0],max(dp[i-1][j][4],max(dp[i-1][j-1][4],max(dp[i-1][j-1][1],dp[i-1][j-1][2]))))+a[i][0]+a[i][1]:-1e9; printf("%d\n",max(dp[n][k][0],max(dp[n][k][1],max(dp[n][k][2],max(dp[n][k][3],dp[n][k][4]))))); } }