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
",ans);
58     return 0;
59 }
View Code
原文地址:https://www.cnblogs.com/jimzeng/p/bzoj1084.html