洛谷传送门
题目描述
windy有 N 条木板需要被粉刷。 每条木板被分为 M 个格子。 每个格子要被刷成红色或蓝色。
windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。
如果windy只能粉刷 T 次,他最多能正确粉刷多少格子?
一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。
输入输出格式
输入格式:
第一行包含三个整数,N M T。
接下来有N行,每行一个长度为M的字符串,’0’表示红色,’1’表示蓝色。
输出格式:
包含一个整数,最多能正确粉刷的格子数。
输入输出样例
输入样例
3 6 3
111111
000000
001100
输出样例
16
说明
30%的数据,满足 1<=N 1 <= N , M<=10 M <= 10 ; 0<=T<=100 0 <= T <= 100 。
100%的数据,满足 1<=N 1 <= N , M<=50 M <= 50 ; 0<=T<=2500 0 <= T <= 2500 。
解题分析
一开始还以为是可以竖着涂和横着涂…那么这样显然不可做啊 最后发现原来是只能涂横排, 所以算出每一排涂
1→T
1
→
T
次能正确涂的最多的格子数, 再进行一次01背包即可。
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#define R register
#define gc getchar()
#define W while
#define IN inline
using namespace std;
char data[55][2505];
int p[55][55][2505], dp[55][2505];
int hang, lie, tim;
IN int findit(const int &row, const int &lef, const int &rig)
{//在剩下部分找, 当然是哪种颜色多涂哪种
int rt = 0, oth;
for (R int i = lef; i <= rig; ++i)
{if(data[row][i] == '1') rt ++;}
oth = rig - lef + 1 - rt;
return max(oth, rt);
}
int main()
{
scanf("%d%d%d", &hang, &lie, &tim);
for (R int i = 1; i <= hang; ++i) scanf("%s", data[i] + 1);
for (R int i = 1; i <= hang; ++i)
for (R int j = 1; j <= lie; ++j)
for (R int k = 1; k <= j && k <= tim; ++k)
for (R int cur = 0; cur < j; ++cur)
{
p[i][j][k] = max(p[i][j][k], p[i][cur][k - 1] + findit(i, cur + 1, j));
}
for (R int i = 1; i <= hang; ++i)
{
for (R int j = 1; j <= tim; ++j)
{
for (R int k = 0; k <= j; ++k)
{
dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + p[i][lie][k]);
}
}
}
printf("%d", dp[hang][tim]);
return 0;
}