BZOJ1296 [SCOI2009]粉刷匠 动态规划 分组背包
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1296
题意概括
有 N 条木板需要被粉刷。 每条木板被分为 M 个格子。 每个格子要被刷成红色或蓝色。 windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。 如果windy只能粉刷 T 次,他最多能正确粉刷多少格子? 一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。
题解
对于每一个木板,我们用f[i][j]表示在前i个里面刷j次的ans。
然后对于n个木板,分组背包就可以了。
代码
#include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cmath> using namespace std; const int N=50+5,T=N*N; int n,m,t,a[N],f[N][N],g[T]; int main(){ scanf("%d%d%d",&n,&m,&t); memset(g,0,sizeof g); while (n--){ char str[N]; scanf("%s",str+1); for (int i=1;i<=m;i++) a[i]=str[i]-48; int bar[2]; memset(f,0,sizeof f); for (int i=1;i<=m;i++) for (int j=1;j<=m;j++){ memset(bar,0,sizeof bar); bar[a[i]]++; for (int k=i-1;k>=0;k--){ f[i][j]=max(f[i][j],f[k][j-1]+max(bar[0],bar[1])); bar[a[k]]++; } } for (int i=t;i>=0;i--) for (int j=0;j<=m&&i+j<=t;j++) g[i+j]=max(g[i+j],g[i]+f[m][j]); } printf("%d",g[t]); return 0; }