BZOJ 1296 [SCOI2009]粉刷匠

来源:互联网 发布:c语言不等于号怎么打 编辑:程序博客网 时间:2024/05/17 05:59

一开始看错数据范围,搞了一个O(Tn2m2)的,然后就GG了。
这种做法的思路是,枚举当前状态,可以继续涂此层剩余,也可以涂他层,一分类讨论即可。

后来发现这种做法肯定有大量重复,而且每行之间独立,不必将每行的状态混在一起,于是每行dp搞用cost最多的得分,然后行与行之间分组dp就好了。

TLE:

#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=55;const int maxt=2505;int n,m,t;char s[maxn][maxn];int sum[maxn][maxn];int dp[maxt][maxn][maxn];inline int getans(int x,int l,int r){    return max(sum[x][r]-sum[x][l-1],r-l+1-(sum[x][r]-sum[x][l-1]));}int main(){    scanf("%d%d%d",&n,&m,&t);    for(int i=1;i<=n;i++)        scanf("%s",s[i]+1);//初始化     for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            sum[i][j]=sum[i][j-1]+(s[i][j]=='0');    for(int i=1;i<=n;i++)        for(int k=1;k<=m;k++)dp[1][i][k]=getans(i,1,k);    for(int i=2;i<=t;i++)    {        for(int j=1;j<=n;j++)//层数        {            for(int k=1;k<=m;k++)//个数             {                //本层状态                 for(int l=k+1;l<=m;l++)                    dp[i][j][l]=max(dp[i][j][l],dp[i-1][j][k]+getans(j,k+1,l));                //别层状态                for(int l=j+1;l<=n;l++)                    for(int p=1;p<=m;p++)                        dp[i][l][p]=max(dp[i][l][p],dp[i-1][j][k]+getans(l,1,p));            }        }    }    int ans=0;    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            ans=max(ans,dp[t][i][j]);    printf("%d",ans);}

AC:

#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;const int maxn=105;const int maxt=2505;int n,m,t;char s[maxn][maxn];int sum[maxn][maxn];int dp[maxn][maxt],f[maxn][maxn][maxn];inline int getans(int x,int l,int r){    return max(sum[x][r]-sum[x][l-1],r-l+1-(sum[x][r]-sum[x][l-1]));}int main(){    scanf("%d%d%d",&n,&m,&t);    for(int i=1;i<=n;i++)        scanf("%s",s[i]+1);//初始化     for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            sum[i][j]=sum[i][j-1]+(s[i][j]=='0');//每层独立dp     for(int i=1;i<=n;i++)//层数     {        for(int l=1;l<=m;l++)            f[i][1][l]=getans(i,1,l);        for(int j=2;j<=m;j++)//次数             for(int k=j-1;k<=m;k++)//上次结尾                for(int l=k+1;l<=m;l++)//本次结尾                     f[i][j][l]=max(f[i][j][l],f[i][j-1][k]+getans(i,k+1,l));    }    /*for(int i=1;i<=m;i++)        for(int j=i;j<=m;j++)            printf("%d%c",f[1][i][j],j==m?'\n':' '); *///分组背包dp     for(int i=1;i<=n;i++)//层数         for(int j=0;j<=t;j++)//上次剩余             for(int k=0;k<=min(m,j);k++)//本次使用                 dp[i][j-k]=max(dp[i][j-k],dp[i-1][j]+f[i][k][m]);    printf("%d",dp[n][0]);    return 0;}
原创粉丝点击