luogu 4158 粉刷匠 dp套dp

dp套dp

每个木板是个递推的dp,外部是个分组背包

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std;
const int N=55;
const int T=2550;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;}
int n,m,t,f[N][N],dp[N][T],s[N];char s1[N];
int main(){
    n=read();m=read();t=read();
    for(int i=1;i<=n;i++){
        memset(f,0,sizeof f);
        memset(s,0,sizeof s);
        scanf("%s",s1+1);
        for(int j=1;j<=m;j++) s[j]=s[j-1]+(s1[j]=='1');
        //提前预处理字符串贡献,利用前缀和
        for(int j=1;j<=m;j++)
        for(int k=1;k<=m;k++)// i,j代表前i个字母刷了j个
        for(int z=0;z<j;z++){
            int dis=s[j]-s[z];
            f[j][k]=max(f[j][k],f[z][k-1]+max(dis,j-z-dis));
            // f[j][k] 代表本行中前j格涂了k次的最大收益
        }
        for(int j=1;j<=t;j++){
            int top=min(j,m);
            //防止出现实际上不存在的格子
            for(int k=1;k<=top;k++)
            dp[i][j]=max(dp[i][j],dp[i-1][j-k]+f[m][k]);}
            // 就算本条木板中有些不涂,向后递推,答案也不会变得更劣,所以每行的最优答案集中在f[m]上
    }int ans=0;// dp i,j分别代表前i行涂了j个格子的情况    
    for(int i=1;i<=t;i++) ans=max(ans,dp[n][i]);
    printf("%d\n",ans);return 0;
}

 

posted @ 2018-09-03 19:09  ASDIC减除  阅读(113)  评论(0编辑  收藏  举报