[SCOI2009] 粉刷匠
题目传送-Luogu4158
题目传送-BZOJ1296
题意:
有\(n\)条长度为\(m\)的木板,每一格有一个目标颜色(一共两种),初始无色。
每次操作可以将一个木板的一段区间染成一种颜色,一个格子最多只能染一次。总共能有\(k\)次操作机会
问最多能染多少符合目标颜色的格子
\(n,m \le 50,T \le 2500\)
题解:
每行\(DP\)一下
总共背包一下
没什么好讲的。。
过程:
一切顺利
代码:
const int N=60,M=60,T=2510;
int n,m,K;
int f[N][M][T][3];
int g[N][T],val[N][T];
char s[M];
inline int trans(char ch) {
return ch-'0';
}
// inline void Min(int &x,int y) {x=min(x,y);}
inline void Max(int &x,int y) {x=max(x,y);}
signed main() {
read(n); read(m); read(K);
mem(f,-63);
for(int i=1;i<=n;i++) {
scanf("%s",s+1);
f[i][0][0][2]=0;
for(int j=1;j<=m;j++) {
for(int k=0;k<=min(j,K);k++)
for(int col=0;col<3;col++) {
int fl=(col==trans(s[j]));
f[i][j][k][col]=f[i][j-1][k][col]+fl;
if(k>0) {
if(col!=2) {
for(int fr=0;fr<3;fr++)
Max(f[i][j][k][col],f[i][j-1][k-1][fr]+fl);
} else {
for(int fr=0;fr<3;fr++)
Max(f[i][j][k][col],f[i][j-1][k][fr]);
}
}
}
}
}
for(int i=1;i<=n;i++)
for(int k=0;k<=min(m,K);k++)
for(int col=0;col<3;col++)
Max(val[i][k],f[i][m][k][col]);
for(int i=1;i<=n;i++) {
for(int k=0;k<=K;k++)
for(int c=0;c<=min(k,m);c++)
Max(g[i][k],g[i-1][k-c]+val[i][c]);
}
// for(int i=1;i<=n;i++) {
// for(int j=0;j<=K;j++)
// printf("%d ",g[i][j]);
// puts("");
// }
printf("%d\n",g[n][K]);
return 0;
}
/*
3 6 3
111111
000000
001100
*/
用时:15min