动态规划 BZOJ1084 [SCOI2005]最大子矩阵
1084: [SCOI2005]最大子矩阵
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2771 Solved: 1379
[Submit][Status][Discuss]
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
HINT
Source
通读题目有时很重要,比如这个题……
发现可以根据m=1和m=2分类讨论地写,用前缀和容易想到,代码通俗易懂
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,m,k,a; 7 int sum[110][3],f[110][12],g[110][110][12]; 8 int main(){ 9 scanf("%d%d%d",&n,&m,&k); 10 for(int i=1;i<=n;i++) 11 for(int j=1;j<=m;j++){ 12 scanf("%d",&a); 13 sum[i][j]=sum[i-1][j]+a; 14 } 15 if(m==1){ 16 for(int i=1;i<=n;i++) 17 for(int j=1;j<=k;j++){ 18 f[i][j]=f[i-1][j]; 19 for(int p=0;p<=i-1;p++) f[i][j]=max(f[i][j],f[p][j-1]+sum[i][1]-sum[p][1]); 20 } 21 printf("%d\n",f[n][k]); 22 } 23 else{ 24 for(int i=1;i<=n;i++) 25 for(int j=1;j<=n;j++) 26 for(int t=1;t<=k;t++){ 27 g[i][j][t]=max(g[i-1][j][t],g[i][j-1][t]); 28 for(int p=0;p<=i-1;p++) g[i][j][t]=max(g[i][j][t],g[p][j][t-1]+sum[i][1]-sum[p][1]); 29 for(int p=0;p<=j-1;p++) g[i][j][t]=max(g[i][j][t],g[i][p][t-1]+sum[j][2]-sum[p][2]); 30 if(i==j) 31 for(int p=0;p<=i-1;p++) g[i][j][t]=max(g[i][j][t],g[p][p][t-1]+sum[i][1]-sum[p][1]+sum[i][2]-sum[p][2]); 32 } 33 printf("%d\n",g[n][n][k]); 34 } 35 return 0; 36 }