一开始看到这道题,由于觉得m <= 2, 所以觉得这是道水题,回去后想了一下。在晚上来机房的时候已经想出来了,但是我必须承认细节决定成败。远在一个小时前我就已经把算法的主体都写好了,但是就是一直WA,为什么就是各种粗心,真心想捏死自己。一个小时就这么白白浪费了。我希望明天的我能变得强大一点。在有了今日惨痛的教训之后。
这道题并不难。用d[i][j][k] 来表示状态。i表示第几行,j表示之前取了多少个矩阵,k表示上一行的状态。即上一行的矩阵取法。如果k == 0 那么没有一个矩阵延伸到上一行,如果 k == 1,那么有一个矩阵延伸到上一行的左边那个数, k == 2 时 那么有一个矩阵延伸到上一行的右边那个数, k == 3 时分别有两个矩阵延伸到上一个的两个数。当k == 4 时有一个矩阵延伸到上一行的两个数。那么状态转移方程应该就不难写了。细心细心,再细心。谦虚,谦虚,再谦虚。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define INF 0x3fffffff 5 #define rep(i,j,k) for(int i = j; i <= k; i++) 6 #define maxn 120 7 using namespace std; 8 9 int d[maxn][15][5] = {0}; 10 int a[maxn][3] = {0}; 11 12 int read() 13 { 14 int s = 0, t = 1; char c = getchar(); 15 while( !isdigit(c) ){ 16 if( c == '-' ) t = -1; c = getchar(); 17 } 18 while( isdigit(c) ){ 19 s = s * 10 + c - '0'; c = getchar(); 20 } 21 return s * t; 22 } 23 24 int main() 25 { 26 int n = read(), m = read(), k = read(); 27 rep(i,0,n) rep(j,0,k) rep(l,0,4) d[i][j][l] = -INF; 28 d[0][0][0] = 0; 29 rep(i,1,n){ 30 rep(j,1,m){ 31 a[i][j] = read(); 32 } 33 } 34 rep(i,0,n-1) 35 rep(j,0,k){ 36 if( m == 1 ){ 37 rep(l,0,1) d[i+1][j][0] = max(d[i+1][j][0],d[i][j][l]); 38 d[i+1][j][1] = max(d[i+1][j][1],d[i][j][1]+a[i+1][1]); 39 d[i+1][j+1][1] = max(d[i+1][j+1][1],d[i][j][0]+a[i+1][1]); 40 } 41 else{ 42 rep(l,0,4) d[i+1][j][0] = max(d[i+1][j][0],d[i][j][l]); 43 d[i+1][j][1] = max(d[i+1][j][1],d[i][j][1]+a[i+1][1]); 44 d[i+1][j][1] = max(d[i+1][j][1],d[i][j][3]+a[i+1][1]); 45 d[i+1][j+1][1] = max(d[i+1][j+1][1],d[i][j][0]+a[i+1][1]); 46 d[i+1][j+1][1] = max(d[i+1][j+1][1],d[i][j][2]+a[i+1][1]); 47 d[i+1][j+1][1] = max(d[i+1][j+1][1],d[i][j][4]+a[i+1][1]); 48 49 d[i+1][j][2] = max(d[i+1][j][2],d[i][j][2]+a[i+1][2]); 50 d[i+1][j][2] = max(d[i+1][j][2],d[i][j][3]+a[i+1][2]); 51 d[i+1][j+1][2] = max(d[i+1][j+1][2],d[i][j][0]+a[i+1][2]); 52 d[i+1][j+1][2] = max(d[i+1][j+1][2],d[i][j][1]+a[i+1][2]); 53 d[i+1][j+1][2] = max(d[i+1][j+1][2],d[i][j][4]+a[i+1][2]); 54 55 d[i+1][j][3] = max(d[i+1][j][3],d[i][j][3]+a[i+1][2]+a[i+1][1]); 56 d[i+1][j+1][3] = max(d[i+1][j+1][3],d[i][j][1]+a[i+1][2]+a[i+1][1]); 57 d[i+1][j+1][3] = max(d[i+1][j+1][3],d[i][j][2]+a[i+1][2]+a[i+1][1]); 58 d[i+1][j+2][3] = max(d[i+1][j+2][3],d[i][j][0]+a[i+1][2]+a[i+1][1]); 59 d[i+1][j+1][3] = max(d[i+1][j+1][3],d[i][j][4]+a[i+1][2]+a[i+1][1]); 60 61 d[i+1][j][4] = max(d[i+1][j][4],d[i][j][4]+a[i+1][2]+a[i+1][1]); 62 rep(l,0,3) d[i+1][j+1][4] = max(d[i+1][j+1][4],d[i][j][l]+a[i+1][2]+a[i+1][1]); 63 } 64 } 65 int ans; 66 ans = max(d[n][k][0],d[n][k][1]); 67 if( m == 2 ) rep(l,2,4) ans = max(ans,d[n][k][l]); 68 cout<<ans<<endl; 69 return 0; 70 }
1084: [SCOI2005]最大子矩阵
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1851 Solved: 927
[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