[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

posted @ 2018-08-25 20:28  functionendless  阅读(207)  评论(0编辑  收藏  举报