[bzoj1084][SCOI2005]最大子矩阵

呃本来今天是想写一下今天ditoly出的丧题的,但是没有包啊好尴尬,明天测一下再发吧。所以今天去bzoj水了一题充数。


---------------------------分割线

题意:给丁一个n*m的矩阵,最多选出k个不重叠子矩阵,求最大的元素和。n<=100,m<=2,k<=10

题解:没啥好说的啊m=1就是普及组水平dp吧??然后m=2多一维,f[k][i][j]表示第一行前i个,第二行前j个选出k个子矩阵的最大值。

复杂度n^3*k

#include<iostream>
#include<cstdio>
#define MAXN 100
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

int F[12][MAXN+5];
int f[12][MAXN+5][MAXN+5];
int n,m,K;
int s[3][MAXN+5];

void solve1()
{
    for(int k=1;k<=K;k++)
        for(int i=1;i<=n;i++)
        {
            F[k][i]=F[k][i-1];
            for(int j=0;j<i;j++)
                F[k][i]=max(F[k][i],F[k-1][j]+s[1][i]-s[1][j]);
        }
    int ans=0;
    for(int i=0;i<=K;i++)ans=max(ans,F[i][n]);
    printf("%d\n",ans);
}

void solve2()
{
    for(int i=1;i<=n;i++)s[0][i]=s[1][i]+s[2][i];
    for(int k=1;k<=K;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                f[k][i][j]=max(f[k][i-1][j],f[k][i][j-1]);
                for(int l=0;l<i;l++)
                    f[k][i][j]=max(f[k][i][j],f[k-1][l][j]+s[1][i]-s[1][l]);
                for(int l=0;l<j;l++)
                    f[k][i][j]=max(f[k][i][j],f[k-1][i][l]+s[2][j]-s[2][l]);
                if(i==j)  for(int l=0;l<i;l++)
                    f[k][i][j]=max(f[k][i][j],f[k-1][l][l]+s[0][i]-s[0][l]);
              //  cout<<k<<" "<<i<<" "<<j<<" "<<f[k][i][j]<<endl;
            }
    int ans=0;
    for(int i=0;i<=K;i++)ans=max(ans,f[i][n][n]);
    printf("%d\n",ans);
}

int main()
{
    n=read();m=read();K=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            s[j][i]=read()+s[j][i-1];
    if(m==1) solve1();
    else solve2();
    return 0;
}

 

posted @ 2017-03-09 21:08  FallDream  阅读(230)  评论(0编辑  收藏