BZOJ1084 [SCOI2005] 最大子矩阵
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1084
Description
这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵不能相互重叠。
Input
第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767)。
Output
只有一行为k个子矩阵分值之和最大为多少。
在一次AC背后是不知多少次的WA……真是呵呵
dp[i][j][k]表示到第i行,取了j个,k表示这一行的状态:0为上下都不取,1为去上面,2为取下面,3为上下都取且不相连,4为上下都取且相连
然后同样的状态在两行视为连在一起不能拆开,第一次推错了,好歹说一说嘛。
然后数组大小开到刚刚好101就WA,开到110就AC,算我作死。
然后状态转移方程有好多好多道,看代码吧。
然后就没有然后了。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define rep(i,l,r) for(int i=l; i<=r; i++) 6 #define clr(x,y) memset(x,y,sizeof(x)) 7 using namespace std; 8 const int INF = 0x3fffffff; 9 int n,m,k,ans=-INF,num[110][3],dp[110][20][5]; 10 inline int read(){ 11 int ans = 0, f = 1; 12 char c = getchar(); 13 while (!isdigit(c)){ 14 if (c == '-') f = -1; 15 c = getchar(); 16 } 17 while (isdigit(c)){ 18 ans = ans * 10 + c - '0'; 19 c = getchar(); 20 } 21 return ans * f; 22 } 23 int main(){ 24 n = read(); m = read(); k = read(); 25 rep(i,1,n) rep(j,1,m) num[i][j] = read(); 26 rep(i,0,n) rep(j,0,k) rep(l,0,4) dp[i][j][l] = -INF; 27 dp[0][0][0] = 0; 28 rep(i,0,n-1) rep(j,0,k){ 29 if (m == 1){ 30 rep(l,0,1) dp[i+1][j][0] = max(dp[i+1][j][0],dp[i][j][l]); 31 dp[i+1][j][1] = max(dp[i+1][j][1],dp[i][j][1] + num[i+1][1]); 32 dp[i+1][j+1][1] = max(dp[i+1][j+1][1],dp[i][j][0] + num[i+1][1]); 33 } 34 else{ 35 rep(l,0,4) dp[i+1][j][0] = max(dp[i+1][j][0],dp[i][j][l]); 36 dp[i+1][j][1] = max(dp[i+1][j][1],dp[i][j][1] + num[i+1][1]); 37 dp[i+1][j][1] = max(dp[i+1][j][1],dp[i][j][3] + num[i+1][1]); 38 dp[i+1][j+1][1] = max(dp[i+1][j+1][1],dp[i][j][0] + num[i+1][1]); 39 dp[i+1][j+1][1] = max(dp[i+1][j+1][1],dp[i][j][2] + num[i+1][1]); 40 dp[i+1][j+1][1] = max(dp[i+1][j+1][1],dp[i][j][4] + num[i+1][1]); 41 dp[i+1][j][2] = max(dp[i+1][j][2],dp[i][j][2] + num[i+1][2]); 42 dp[i+1][j][2] = max(dp[i+1][j][2],dp[i][j][3] + num[i+1][2]); 43 dp[i+1][j+1][2] = max(dp[i+1][j+1][2],dp[i][j][0] + num[i+1][2]); 44 dp[i+1][j+1][2] = max(dp[i+1][j+1][2],dp[i][j][1] + num[i+1][2]); 45 dp[i+1][j+1][2] = max(dp[i+1][j+1][2],dp[i][j][4] + num[i+1][2]); 46 dp[i+1][j][3] = max(dp[i+1][j][3],dp[i][j][3] + num[i+1][1] + num[i+1][2]); 47 dp[i+1][j+1][3] = max(dp[i+1][j+1][3],dp[i][j][1] + num[i+1][1] + num[i+1][2]); 48 dp[i+1][j+1][3] = max(dp[i+1][j+1][3],dp[i][j][2] + num[i+1][1] + num[i+1][2]); 49 dp[i+1][j+2][3] = max(dp[i+1][j+2][3],dp[i][j][0] + num[i+1][1] + num[i+1][2]); 50 dp[i+1][j+2][3] = max(dp[i+1][j+2][3],dp[i][j][4] + num[i+1][1] + num[i+1][2]); 51 dp[i+1][j][4] = max(dp[i+1][j][4],dp[i][j][4] + num[i+1][1] + num[i+1][2]); 52 rep(l,0,3) dp[i+1][j+1][4] = max(dp[i+1][j+1][4],dp[i][j][l] + num[i+1][1] + num[i+1][2]); 53 } 54 } 55 ans = max(ans,dp[n][k][0]); ans = max(ans,dp[n][k][1]); 56 if (m == 2) ans = max(ans,dp[n][k][2]), ans = max(ans,dp[n][k][3]), ans = max(ans,dp[n][k][4]); 57 printf("%d\n",ans); 58 return 0; 59 }