bzoj 1296: [SCOI2009]粉刷匠 两次,DP

Description

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

Input

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

Output

输出文件paint.out包含一个整数,最多能正确粉刷的格子数。

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 。

 

思路:

先把每行的最优值用 n*n*n 算出来,

再计算到了 i 行,分成 j 次的最优值。

#include<bits/stdc++.h>
using namespace std;
const int N = 100;
int f[N][N],dp[N][N*N],sum[N];
int n,m,t;
int main(){
	char s[N];
	scanf("%d%d%d",&n,&m,&t);
	for (int i = 1; i <= n; ++i){
		scanf("%s",s+1);
		for (int j = 1; j <= m; ++j)
			sum[j] = sum[j-1] + (s[j] == '1');  //求区间的1的个数。

		for (int j = 1; j <= m; ++j)
			for (int x = 1; x <= m; ++x){
				f[x][j] = 0;  //第 i 行,到 x 列粉刷 j 次的最大值。
				for (int y = 0; y < x; ++y){
					int temp = sum[x] - sum[y];
					f[x][j] = max(f[x][j], f[y][j-1]+max(x-y-temp,temp));
				}
			}

		for (int j = 1; j <= t; ++j){
			int tmp = min(j,m);
			for (int k = 1; k <= tmp; ++k)
				dp[i][j] = max(dp[i][j],dp[i-1][j-k]+f[m][k]);
		}
	}
	int ans = 0;
	for (int i = 1; i <= t; ++i)
		ans = max(ans,dp[n][i]);
	printf("%d\n",ans);
	return 0;
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值