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;
}