bzoj1296 [SCOI2009]粉刷匠

[SCOI2009]粉刷匠

Time Limit: 10 Sec Memory Limit: 162 MB

Description

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

Input

第一行包含三个整数,N M T。 接下来有N行,每行一个长度为M的字符串,'0'表示红色,'1'表示蓝色。

Output

包含一个整数,最多能正确粉刷的格子数。

Sample Input

3 6 3
111111
000000
001100

Sample Output

16

HINT

30%的数据,满足 1 <= N,M <= 10 ; 0 <= T <= 100 。 100%的数据,满足 1 <= N,M <= 50 ; 0 <= T <= 2500 。

太暴力了~真的太暴力了
总结如下:没有什么是一次DP不能解决的,如果有,那就两次。

看了半天,就两次DP吧
由于每根木条之间没有直接的关系,所以先每个木条DP一次,\(dp[i][j]\)表示前\(i\)个格子涂\(j\)次的最优解。
考虑转移:\(dp[i][j]=max(dp[k][j-1] + 最后这一次区间中可以带来的最多贡献)\) (显然1多就涂1,0多就涂0啊)

第二个DP背包一下,呵呵呵~
太暴力啊,这就是暴力美学???


#include<bits/stdc++.h>
using namespace std;
int n, m, T;
char s[55][55];
int g[55][55][2505], f[55][2505];

inline void putit()
{
	scanf("%d%d%d", &n, &m, &T);
	for(int i = 1; i <= n; ++i)	scanf("%s", s[i] + 1);
}

inline int search(int t, int l, int r)
{
	int ret = 0;
	for(int i = l; i <= r; ++i)	if(s[t][i] == '0') ret++;
	ret = max(ret, (r - l + 1) - ret);
	return ret;
}

inline void Dp_1()
{
	for(int p = 1; p <= n; ++p)
		for(int i = 1; i <= m; ++i)
			for(int j = 1; j <= i && j <= T; ++j)
				for(int k = 0; k < i; ++k)
					g[p][i][j] = max(g[p][i][j], g[p][k][j - 1] + search(p, k + 1, i));
}

inline void Dp_2()
{
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= T; ++j)
			for(int k = 0; k <= j; ++k)
				f[i][j] = max(f[i][j], f[i - 1][j - k] + g[i][m][k]);
}

int main()
{
	putit();
	Dp_1();
	Dp_2();
	printf("%d", f[n][T]);
	return 0;
}

posted @ 2018-03-19 12:10  沛霖  阅读(167)  评论(0编辑  收藏  举报