粉刷匠

粉刷匠

\(n\) 条木板需要被粉刷。 每条木板被分为 \(m\) 个格子。 每个格子要被刷成红色或蓝色。每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。 如果只能粉刷 \(T\) 次,他最多能正确粉刷多少格子? 一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。

\(1\le n,m\le 50,0\le T\le 2500\)

image-20230827193239047

两个部分,一个线性 DP,一个分组背包。

#include<cstdio>
#include<algorithm>
#include<functional>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while

const int N=60,M=2510;
int n,m,t,dp[N][N][N][2],f[N][M],a[N];
char s[N][N];
void init(int f[][N][2],char s[]){
    E(i, m)
        E(j, m){
            if(s[i]=='0')f[i][j][0]=max(f[i-1][j][0],f[i-1][j-1][1])+1,f[i][j][1]=f[i-1][j][1];
            else f[i][j][1]=max(f[i-1][j][1],f[i-1][j-1][0])+1,f[i][j][0]=f[i-1][j][0];
        }
    // L(i, m+1)printf("%d ",max(f[m][i][0],f[m][i][1]));
    // puts("");
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    #endif
    scanf("%d%d%d",&n,&m,&t);
    E(i, n)scanf("%s",s[i]+1);
    if(t<=n){//贪心可以删去
        E(i, n){
            E(j, m)a[i]+=s[i][j]=='1';
            a[i]=max(a[i],m-a[i]);
        }
        sort(a+1,a+1+n,greater<int>());
        int ans=0;
        E(i, t)ans+=a[i];
        printf("%d",ans);
        return 0;
    }
    E(i, n)init(dp[i],s[i]);
    E(i, n)
        L(j, t+1){
            f[i][j]=f[i-1][j];
            L(k, m+1)
                if(j>=k)
                    f[i][j]=max(f[i][j],f[i-1][j-k]+max(dp[i][m][k][0],dp[i][m][k][1]));
        }
    printf("%d",f[n][t]);
    return 0;
}
posted @ 2023-08-27 19:36  wscqwq  阅读(7)  评论(0编辑  收藏  举报