bzoj 1084: [SCOI2005]最大子矩阵
1084: [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
ACTY真神牛!!!(大家可以去bzoj上搜搜)
——————以下题解————————
m最大只有2
状压吧,用0,1,2,3,4表示一行的状态
0:表示一个都不选
1:表示选左边一个
2:表示选右边一个
3:表示2个作为一个整体选
4:表示2个分开来选
DP的转移就不多说了。。。
代码写得有些难看,忍一忍吧。。
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; const int Min=-2000000000; int n,m,v,k,i,j,l,ans,a[105][3],f[105][15][5]; int main() { scanf("%d%d%d",&n,&m,&v); for(i=1;i<=n;i++) for(j=1;j<=m;j++) scanf("%d",&a[i][j]); for(i=1;i<=n;i++) for(j=0;j<=v;j++) for(k=0;k<=4;k++) f[i][j][k]=Min; f[1][0][0]=0; f[1][1][1]=a[1][1]; f[1][1][2]=a[1][2]; f[1][1][3]=a[1][1]+a[1][2]; f[1][2][4]=a[1][1]+a[1][2]; for(i=1;i<n;i++) for(j=0;j<=v;j++) { if(m==1) { for(k=0;k<=1;k++) f[i+1][j][0]=max(f[i+1][j][0],f[i][j][k]); f[i+1][j][1]=max(f[i+1][j][1],f[i][j][1]+a[i+1][1]); f[i+1][j+1][1]=max(f[i+1][j+1][1],f[i][j][1]+a[i+1][1]); f[i+1][j+1][1]=max(f[i+1][j+1][1],f[i][j][0]+a[i+1][1]); //cout<<f[4][3][1]<<' '<<i<<' '<<j<<' '<<f[i][j][0]<<' '<<f[i][j][1]<<endl; } else { //0 for(k=0;k<=4;k++) f[i+1][j][0]=max(f[i+1][j][0],f[i][j][k]); //1 f[i+1][j][1]=max(f[i+1][j][1],f[i][j][1]+a[i+1][1]); f[i+1][j][1]=max(f[i+1][j][1],f[i][j][4]+a[i+1][1]); f[i+1][j+1][1]=max(f[i+1][j+1][1],f[i][j][1]+a[i+1][1]); f[i+1][j+1][1]=max(f[i+1][j+1][1],f[i][j][0]+a[i+1][1]); f[i+1][j+1][1]=max(f[i+1][j+1][1],f[i][j][4]+a[i+1][1]); //2 f[i+1][j][2]=max(f[i+1][j][2],f[i][j][2]+a[i+1][2]); f[i+1][j][2]=max(f[i+1][j][2],f[i][j][4]+a[i+1][2]); f[i+1][j+1][2]=max(f[i+1][j+1][2],f[i][j][0]+a[i+1][2]); f[i+1][j+1][2]=max(f[i+1][j+1][2],f[i][j][2]+a[i+1][2]); f[i+1][j+1][2]=max(f[i+1][j+1][2],f[i][j][4]+a[i+1][2]); //3 f[i+1][j][3]=max(f[i+1][j][3],f[i][j][3]+a[i+1][1]+a[i+1][2]); f[i+1][j+1][3]=max(f[i+1][j+1][3],f[i][j][0]+a[i+1][1]+a[i+1][2]); f[i+1][j+1][3]=max(f[i+1][j+1][3],f[i][j][3]+a[i+1][1]+a[i+1][2]); //4 f[i+1][j][4]=max(f[i+1][j][4],f[i][j][4]+a[i+1][1]+a[i+1][2]); f[i+1][j+1][4]=max(f[i+1][j+1][4],f[i][j][1]+a[i+1][1]+a[i+1][2]); f[i+1][j+1][4]=max(f[i+1][j+1][4],f[i][j][2]+a[i+1][1]+a[i+1][2]); f[i+1][j+2][4]=max(f[i+1][j+2][4],f[i][j][0]+a[i+1][1]+a[i+1][2]); f[i+1][j+2][4]=max(f[i+1][j+2][4],f[i][j][1]+a[i+1][1]+a[i+1][2]); f[i+1][j+2][4]=max(f[i+1][j+2][4],f[i][j][2]+a[i+1][1]+a[i+1][2]); f[i+1][j+2][4]=max(f[i+1][j+2][4],f[i][j][4]+a[i+1][1]+a[i+1][2]); } } ans=max(f[n][v][0],f[n][v][1]); if(m==2) for(i=2;i<=4;i++) ans=max(ans,f[n][v][i]); cout<<ans; return 0; }
一念起,天涯咫尺; 一念灭,咫尺天涯。