[BZOJ1084][SCOI2005]最大子矩阵(dp)
2017-04-19 07:38
477 查看
题目描述
传送门题目大意:有一个n*m的矩阵,请你选出其中至多k个子矩阵,使得这些子矩阵分值之和最大。注意:选出的子矩阵不能相互重叠。(1<=m<=2)
题解
我竟然把m分开写了m=1随便写
m=2预处理up(i,j),down(i,j),all(i,j)表示在区间[i,j]中的第一行、第二行、两行的最长连续子序列和,f(k,i,j,0/1/2)表示选了k个,在区间[i,j]中,只选第一行/只选第二行/两行都可能有的最大值,枚举断点、上下两行选的个数,直接转移。
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; int n,m,k; namespace type1 { int ans; int a[105],s[105],f[15][105]; void solve() { for (int i=1;i<=n;++i) scanf("%d",&a[i]),s[i]=s[i-1]+a[i]; memset(f,128,sizeof(f)); for (int i=0;i<=n;++i) f[0][i]=0; for (int i=1;i<=k;++i) for (int j=i;j<=n;++j) { f[i][j]=f[i][j-1]; for (int p=0;p<j;++p) f[i][j]=max(f[i][j],f[i-1][p]+s[j]-s[p]); } for (int i=1;i<=k;++i) ans=max(ans,f[i] ); printf("%d\n",ans); } } namespace type2 { int ans,inf,a[5][105],sum[105]; int f[15][105][105][3],up[105][105],down[105][105],all[105][105]; int Max(int a,int b,int c) { if (a<b) a=b; if (a<c) a=c; return a; } void solve() { for (int i=1;i<=n;++i) for (int j=1;j<=2;++j) scanf("%d",&a[j][i]); for (int i=1;i<=n;++i) sum[i]=a[1][i]+a[2][i]; memset(up,128,sizeof(up)),memset(down,128,sizeof(down)),memset(all,128,sizeof(all)); for (int i=1;i<=n;++i) { up[i][i]=a[1][i],down[i][i]=a[2][i],all[i][i]=sum[i]; for (int j=i+1;j<=n;++j) up[i][j]=max(up[i][j-1]+a[1][j],a[1][j]), down[i][j]=max(down[i][j-1]+a[2][j],a[2][j]), all[i][j]=max(all[i][j-1]+sum[j],sum[j]); for (int j=i+1;j<=n;++j) up[i][j]=max(up[i][j],up[i][j-1]), down[i][j]=max(down[i][j],down[i][j-1]), all[i][j]=max(all[i][j],all[i][j-1]); } memset(f,128,sizeof(f));inf=f[0][0][0][0]; for (int i=1;i<=n;++i) for (int j=1;j<=n;++j) f[1][i][j][0]=up[i][j],f[1][i][j][1]=down[i][j], f[1][i][j][2]=Max(up[i][j],down[i][j],all[i][j]); for (int i=2;i<=k;++i) { for (int len=1;len<=n;++len) for (int l=1;l<=n-len+1;++l) { int r=l+len-1; for (int s=0;s<=2;++s) for (int p=l;p<r;++p) for (int q=0;q<=i;++q) if (f[q][l][p][s]!=inf&&f[i-q][p+1][r][s]!=inf) f[i][l][r][s]=max(f[i][l][r][s],f[q][l][p][s]+f[i-q][p+1][r][s]); f[i][l][r][2]=Max(f[i][l][r][0],f[i][l][r][1],f[i][l][r][2]); for (int j=0;j<=k;++j) if (f[j][l][r][0]!=inf&&f[i-j][l][r][1]!=inf) f[i][l][r][2]=max(f[i][l][r][2],f[j][l][r][0]+f[i-j][l][r][1]); } } for (int i=1;i<=k;++i) ans=max(ans,f[i][1] [2]); printf("%d\n",ans); } } int main() { scanf("%d%d%d",&n,&m,&k); if (m==1) type1::solve(); else type2::solve(); }
相关文章推荐
- 【BZOJ 1084】 1084: [SCOI2005]最大子矩阵 (DP)
- bzoj1084 [SCOI2005]最大子矩阵(dp)
- bzoj 1084: [SCOI2005]最大子矩阵 (DP)
- [DP] bzoj1084: [SCOI2005]最大子矩阵
- 【BZOJ 1084】 [SCOI2005]最大子矩阵(DP)
- [bzoj1084][SCOI2005]最大子矩阵(DP)
- 【BZOJ】1084: [SCOI2005]最大子矩阵(DP)
- [BZOJ 1084] SCOI 2005 最大子矩阵 · 简单DP
- bzoj1084: [SCOI2005]最大子矩阵(dp)
- 【BZOJ1084】【杂题DP】[SCOI2005]最大子矩阵 题解
- bzoj1084: [SCOI2005]最大子矩阵(Dp)
- BZOJ 1084: [SCOI2005]最大子矩阵( dp )
- 【bzoj1084】【洛谷P2331】 【SCOI2005】 最大子矩阵
- BZOJ 1084: [SCOI2005]最大子矩阵 DP
- 洛谷P2331 [SCOI2005]最大子矩阵(BZOJ1084)
- [bzoj1084][SCOI2005]最大子矩阵
- [bzoj 1084--SCOI2005]最大子矩阵
- 【BZOJ 1084】【SCOI 2005】最大子矩阵【DP & 分类讨论】
- bzoj1084: [SCOI2005]最大子矩阵
- BZOJ 1084: [SCOI2005]最大子矩阵【DP】