码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ1084 [SCOI2005]最大子矩阵

时间:2016-08-21 22:45:16      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:

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

Sample Output

9
 
 
正解:DP
解题报告:
  乍一看,感觉像是才做过的那道最大子矩阵和,只不过那道题是固定了三块而这道题是k块,瞬间各种傻眼。
  结果突然发现,m<=2。。。显然可以当做特殊性质。
  f[i][j][k]表示第一列处理到第i个,第二列处理到第j个并且选取了k个子矩阵的最优值。转移的话要不从左边选择一块,要不从右边选择一块,又或者两列都占的矩形,但是只有i、j相等才可能两列都占,否则无法刚好到达i。
  代码如下:
 
 
 
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<algorithm>
 7 using namespace std;
 8 const int MAXN = 150;
 9 int n,m,k;
10 int dp[MAXN][11],f[MAXN][MAXN][11];
11 int a[2][MAXN];
12 int sum[2][MAXN];
13 
14 inline int getint(){
15     int w=0,q=1;char c=getchar();
16     while(c!=- && (c<0 || c>9)) c=getchar();
17     if(c==-) q=-1,c=getchar();
18     while(c>=0 && c<=9) w=w*10+c-0,c=getchar();
19     return w*q;
20 }
21 
22 int main()
23 {
24     n=getint(); m=getint(); k=getint();
25     if(m==1) {//特判只有一列的情况
26     for(int i=1;i<=n;i++) a[0][i]=getint(),sum[0][i]=sum[0][i-1]+a[0][i];
27 
28     for(int i=1;i<=n;i++)
29         for(int l=1;l<=k;l++) { 
30         dp[i][l]=dp[i-1][l];
31         for(int j=0;j<i;j++)
32             dp[i][l]=max(dp[j][l-1]+sum[0][i]-sum[0][j],dp[i][l]);
33         }
34     printf("%d",dp[n][k]);
35 
36     } else{
37     for(int i=1;i<=n;i++) a[0][i]=getint(),sum[0][i]=sum[0][i-1]+a[0][i],a[1][i]=getint(),sum[1][i]=sum[1][i-1]+a[1][i];
38 
39     for(int l=1;l<=k;l++)
40         for(int i=1;i<=n;i++)
41         for(int j=1;j<=n;j++) {
42             f[i][j][l]=max(f[i-1][j][l],f[i][j-1][l]);
43             for(int from=0;from<i;from++) f[i][j][l]=max(f[i][j][l],f[from][j][l-1]+sum[0][i]-sum[0][from]);//枚举从左边转移
44             for(int from=0;from<j;from++) f[i][j][l]=max(f[i][j][l],f[i][from][l-1]+sum[1][j]-sum[1][from]);//枚举从右边转移
45             if(i==j)
46             for(int from=0;from<i;from++)//枚举从两边转移
47                 f[i][j][l]=max(f[i][j][l],f[from][from][l-1]+sum[0][i]-sum[0][from]+sum[1][j]-sum[1][from]);
48         }
49     printf("%d",f[n][n][k]);
50     }
51 
52     return 0;
53 }

 

BZOJ1084 [SCOI2005]最大子矩阵

标签:

原文地址:http://www.cnblogs.com/ljh2000-jump/p/5793708.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!