bzoj1084 [SCOI2005]最大子矩阵

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$。

首先注意到一个性质:$m\leq 2$。

那么我们可以考虑一下,每次一个子矩阵要么只在第一列,要么只在第二列,要么横跨两列。

那么我们可以设$f[i][j][k]$表示第一列到$i$,第二列到$j$,取了$k$个子矩阵的最大值,转移比较简单,不过注意第三种情况只有$i=j$时才能转移。

$m=1$时同理,就是把$f[i][j][k]$换成$f[i][k]$就行了。

 

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define inf (1<<30)
 6 
 7 using namespace std;
 8 
 9 int sum[110][2],g[110][2],n,m,k;
10 
11 il int gi(){
12   RG int x=0,q=1; RG char ch=getchar();
13   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
14   if (ch=='-') q=-1,ch=getchar();
15   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
16   return q*x;
17 }
18 
19 namespace dp1{
20   
21   int f[110][12];
22   
23   int main(){
24     for (RG int i=0;i<=n;++i)
25       for (RG int j=1;j<=k;++j) f[i][j]=-inf;
26     for (RG int i=1;i<=n;++i)
27       for (RG int j=1;j<=k;++j){
28     f[i][j]=max(f[i][j],f[i-1][j]);
29     for (RG int p=0;p<i;++p)
30       f[i][j]=max(f[i][j],f[p][j-1]+sum[i][1]-sum[p][1]);
31       }
32     cout<<f[n][k]; return 0;
33   }
34   
35 }
36 
37 namespace dp2{
38   
39   int f[110][110][12];
40   
41   int main(){
42     for (RG int i=0;i<=n;++i)
43       for (RG int j=0;j<=n;++j)
44     for (RG int p=1;p<=k;++p) f[i][j][p]=-inf;
45     for (RG int i=1;i<=n;++i)
46       for (RG int j=1;j<=n;++j)
47     for (RG int p=1;p<=k;++p){
48       f[i][j][p]=max(f[i][j][p],f[i-1][j][p]);
49       f[i][j][p]=max(f[i][j][p],f[i][j-1][p]);
50       for (RG int pre=0;pre<i;++pre)
51         f[i][j][p]=max(f[i][j][p],f[pre][j][p-1]+sum[i][1]-sum[pre][1]);
52       for (RG int pre=0;pre<j;++pre)
53         f[i][j][p]=max(f[i][j][p],f[i][pre][p-1]+sum[j][2]-sum[pre][2]);
54       if (i==j)
55         for (RG int pre=0;pre<i;++pre)
56           f[i][j][p]=max(f[i][j][p],f[pre][pre][p-1]+sum[i][1]-sum[pre][1]+sum[j][2]-sum[pre][2]);
57     }
58     cout<<f[n][n][k]; return 0;
59   }
60   
61 }
62 
63 int main(){
64 #ifndef ONLINE_JUDGE
65   freopen("matrix.in","r",stdin);
66   freopen("matrix.out","w",stdout);
67 #endif
68   n=gi(),m=gi(),k=gi();
69   for (RG int i=1;i<=n;++i)
70     for (RG int j=1;j<=m;++j) g[i][j]=gi();
71   for (RG int i=1;i<=n;++i){
72     sum[i][1]=sum[i-1][1]+g[i][1];
73     sum[i][2]=sum[i-1][2]+g[i][2];
74   }
75   if (m==1) dp1::main();
76   if (m==2) dp2::main();
77   return 0;
78 }

 

posted @ 2017-10-24 22:26  wfj_2048  阅读(170)  评论(0编辑  收藏  举报