您的位置:首页 > 其它

bzoj1084 [SCOI2005]最大子矩阵

2017-10-24 22:26 387 查看

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]$就行了。

#include <bits/stdc++.h>
#define il inline
#define RG register
#define ll long long
#define inf (1<<30)

using namespace std;

int sum[110][2],g[110][2],n,m,k;

il int gi(){
RG int x=0,q=1; RG char ch=getchar();
while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
if (ch=='-') q=-1,ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
return q*x;
}

namespace dp1{

int f[110][12];

int main(){
for (RG int i=0;i<=n;++i)
for (RG int j=1;j<=k;++j) f[i][j]=-inf;
for (RG int i=1;i<=n;++i)
for (RG int j=1;j<=k;++j){
f[i][j]=max(f[i][j],f[i-1][j]);
for (RG int p=0;p<i;++p)
f[i][j]=max(f[i][j],f[p][j-1]+sum[i][1]-sum[p][1]);
}
cout<<f
[k]; return 0;
}

}

namespace dp2{

int f[110][110][12];

int main(){
for (RG int i=0;i<=n;++i)
for (RG int j=0;j<=n;++j)
for (RG int p=1;p<=k;++p) f[i][j][p]=-inf;
for (RG int i=1;i<=n;++i)
for (RG int j=1;j<=n;++j)
for (RG int p=1;p<=k;++p){
f[i][j][p]=max(f[i][j][p],f[i-1][j][p]);
f[i][j][p]=max(f[i][j][p],f[i][j-1][p]);
for (RG int pre=0;pre<i;++pre)
f[i][j][p]=max(f[i][j][p],f[pre][j][p-1]+sum[i][1]-sum[pre][1]);
for (RG int pre=0;pre<j;++pre)
f[i][j][p]=max(f[i][j][p],f[i][pre][p-1]+sum[j][2]-sum[pre][2]);
if (i==j)
for (RG int pre=0;pre<i;++pre)
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]);
}
cout<<f

[k]; return 0;
}

}

int main(){
#ifndef ONLINE_JUDGE
freopen("matrix.in","r",stdin);
freopen("matrix.out","w",stdout);
#endif
n=gi(),m=gi(),k=gi();
for (RG int i=1;i<=n;++i)
for (RG int j=1;j<=m;++j) g[i][j]=gi();
for (RG int i=1;i<=n;++i){
sum[i][1]=sum[i-1][1]+g[i][1];
sum[i][2]=sum[i-1][2]+g[i][2];
}
if (m==1) dp1::main();
if (m==2) dp2::main();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: