您的位置:首页 > 其它

BZOJ1084 最大子矩阵 [DP]

2017-10-13 21:21 302 查看

1084: [SCOI2005]最大子矩阵

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 3017 Solved: 1510
[Submit][Status][Discuss]

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

HINT

Source

思考

DP,利用前缀和的思想,预处理出前缀和。

因为m只能为1或2,分类讨论:

m=1时为k个普通的最大连续字段和:

设f[i][j]表示前i个数中取出j个矩形的最大和

转移:

f[i][j]=maxf[k][j−1]+s[i]−s[k−1],f[k][j]

复杂度O(n2∗K)

m=2时,设f[i][j][k]表示第一列选到第i个数,第二列选到第j个数时,总共k个子矩形的答案。利用背包DP选与不选的思想:

有①不做②选第一列③选第二列④i==j时选两列的情况。

f[i][j][k]=maxf[i−1][j][k],f[i][j−1][k],w[l][j][k−1]+sum[i][1]−sum[l−1][1](l∈[1,i−1]),f[i][r][k−1]+sum[j][2]−sum[r][2](r∈[1,j−1]),f[l][r][k]+sum[i][1]+sum[i][2]−sum[l][1]−sum[l][2]

复杂度O(n^3*K)

#include<bits/stdc++.h>
#define REP(i,j) for(i=1;i<=j;i++)
#define RET(i,j) for(i=0;i<j;i++)
using namespace std;
int f[120][120][11],n,m,K,stf[120],sts[120];
inline void read(int &res){
static char ch;int flag=1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
int main(){
register int i,j,k,l;
read(n),read(m);read(K);
if(m==1){
REP(i,n)read(k),stf[i]=stf[i-1]+k;
REP(k,K)REP(i,n){
f
[i][k]=f
[i-1][k];
RET(j,i)f
[i][k]=max(f
[i][k],f
[j][k-1]+stf[i]-stf[j]);
}
}else{
REP(i,n)read(j),read(k),stf[i]=stf[i-1]+j,sts[i]=sts[i-1]+k;
REP(k,K)REP(i,n)REP(j,n){
f[i][j][k]=max(f[i-1][j][k],f[i][j-1][k]);
RET(l,i)f[i][j][k]=max(f[i][j][k],f[l][j][k-1]+stf[i]-stf[l]);
RET(l,j)f[i][j][k]=max(f[i][j][k],f[i][l][k-1]+sts[j]-sts[l]);
if(i==j)RET(l,i)
f[i][j][k]=max(f[i][j][k],f[l][l][k-1]+stf[i]-stf[l]+sts[j]-sts[l]);
}
}
printf("%d",f

[K]);
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: