粉刷匠
粉刷匠
有 \(n\) 条木板需要被粉刷。 每条木板被分为 \(m\) 个格子。 每个格子要被刷成红色或蓝色。每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。 如果只能粉刷 \(T\) 次,他最多能正确粉刷多少格子? 一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。
\(1\le n,m\le 50,0\le T\le 2500\)。
两个部分,一个线性 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;
}