BZOJ 1084 [SCOI2005]最大子矩阵

来源:互联网 发布:ios手游模拟器 mac 编辑:程序博客网 时间:2024/05/17 22:47

分类DP

记mx[i][j]表示[j,i]这一个区间里,必须取i的最大连续子段和,用前缀和pre维护。

如果m=1,记f[i][j]表示做到第i行,已经取j个的答案,如果m=2就记f[i][j][k],i和j表示两列分别做到哪一行,已经取k个的答案。

#include<cstdio>#include<cstring>#include<algorithm>#define N 105#define K 15using namespace std;int n, m, k, f[N][K], f1[N][N][K], a[N], b[N], pre[N], pre1[N], pre2[N], mx[N][N], mx1[N][N], mx2[N][N];void solve1(){    for(int i = 1; i <= n; i++)    {        scanf("%d",&a[i]);        pre[i]=pre[i-1]+a[i];    }    for(int i = 1; i <= n; i++)    {        mx[i][i]=a[i];        for(int j = i-1; j >= 1; j--)            mx[i][j]=max(mx[i][j+1],pre[i]-pre[j-1]);    }    for(int i = 1; i <= n; i++)        for(int j = 1; j <= k; j++)        {            f[i][j]=f[i-1][j];            for(int ii = i-1; ii >= 0; ii--)                f[i][j]=max(f[i][j],f[ii][j-1]+mx[i][ii+1]);        }    printf("%d\n",f[n][k]);}void solve2(){    for(int i = 1; i <= n; i++)    {        scanf("%d%d",&a[i],&b[i]);        pre[i]=pre[i-1]+a[i];        pre1[i]=pre1[i-1]+b[i];        pre2[i]=pre[i]+pre1[i];    }    for(int i = 1; i <= n; i++)    {        mx[i][i]=a[i];        mx1[i][i]=b[i];        mx2[i][i]=a[i]+b[i];        for(int j = i-1; j >= 1; j--)        {            mx[i][j]=max(mx[i][j+1],pre[i]-pre[j-1]);            mx1[i][j]=max(mx1[i][j+1],pre1[i]-pre1[j-1]);            mx2[i][j]=max(mx2[i][j+1],pre2[i]-pre2[j-1]);        }    }    int ans=0;    for(int i = 1; i <= n; i++)        for(int j = 1; j <= n; j++)            for(int h = 1; h <= k; h++)            {                f1[i][j][h]=max(f1[i-1][j][h],f1[i][j-1][h]);                for(int ii = i-1; ii >= 0; ii--)                    f1[i][j][h]=max(f1[i][j][h], f1[ii][j][h-1]+mx[i][ii+1]);                for(int jj = j-1; jj >= 0; jj--)                    f1[i][j][h]=max(f1[i][j][h], f1[i][jj][h-1]+mx1[j][jj+1]);                if(i==j)                    for(int ii = i-1; ii >= 0; ii--)                        f1[i][j][h]=max(f1[i][j][h],f1[ii][ii][h-1]+mx2[i][ii+1]);                ans=max(ans,f1[i][j][h]);            }    printf("%d\n",f1[n][n][k]);}int main(){    scanf("%d%d%d",&n,&m,&k);    if(m==1) solve1();    else solve2();}
0 0
原创粉丝点击