1084: [SCOI2005]最大子矩阵
http://www.lydsy.com/JudgeOnline/problem.php?id=1084
RunID | User | Problem | Result | Memory | Time | Language | Code_Length | Submit_Time |
373714 | Liu_Ts | 1084 | Accepted | 1248 kb | 64 ms | C++ | 1227 B | 2013-03-22 08:51:24 |
题意
这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵不能相互重叠。
题解
这题我是一定不会的。。。
可是数据范围比较厉害。偶然翻题解发现原来m≤2,坑爹。
于是DP。
当 m=1 时
g[i][j]表示前i个数字选出j段的最大分值
当 m=2 时
f[i][j][k]表示第一列前i个数字,第二列前j个数字选出k个子矩阵的最大分值
f[i][j][k]=max(f[i-1][j][k],f[i][j-1][k]);
f[i][j][k]=max{f[i][j][k],f[x][j][k-1]+s1[i]-s1[x]};
f[i][j][k]=max{f[i][j][k],f[i][y][k-1]+s2[j]-s2[y]};
当 i=j 时
f[i][j][k]=max{f[i][j][k],f[x][x][k-1]+s1[i]-s1[x]+s2[i]-s2[x]};
#include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int N=101,M=3,K=11; int n,m,p,s[N],s1[N],s2[N]; int g[N][K],f[N][N][K]; void work1() { for(int i=1;i<=n;i++) { scanf("%d",s+i); s[i]+=s[i-1]; } for(int i=1;i<=n;i++) for(int j=1;j<=p;j++) { g[i][j]=g[i-1][j]; for(int k=i-1;k>=0;k--) g[i][j]=max(g[i][j],g[k][j-1]+s[i]-s[k]); } printf("%d\n",g[n][p]); } void work2() { for(int i=1;i<=n;i++) { scanf("%d%d",s1+i,s2+i); s1[i]+=s1[i-1];s2[i]+=s2[i-1]; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=1;k<=p;k++) { f[i][j][k]=max(f[i-1][j][k],f[i][j-1][k]); for(int x=i-1;x>=0;x--) f[i][j][k]=max(f[i][j][k],f[x][j][k-1]+s1[i]-s1[x]); for(int y=j-1;y>=0;y--) f[i][j][k]=max(f[i][j][k],f[i][y][k-1]+s2[j]-s2[y]); if(i==j) for(int x=i-1;x>=0;x--) f[i][j][k]=max(f[i][j][k],f[x][x][k-1]+s1[i]-s1[x]+s2[j]-s2[x]); } printf("%d\n",f[n][n][p]); } int main() { scanf("%d%d%d",&n,&m,&p); if(m==1) work1(); else work2(); }