P4158 [SCOI2009] 粉刷匠
P4158 [SCOI2009] 粉刷匠
题目描述
windy 有 \(N\) 条木板需要被粉刷。 每条木板被分为 \(M\) 个格子。 每个格子要被刷成红色或蓝色。
windy 每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。
如果 windy 只能粉刷 \(T\) 次,他最多能正确粉刷多少格子?
一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。
输入格式
第一行包含三个整数,\(N,M,T\)。
接下来有 \(N\) 行,每行一个长度为 \(M\) 的字符串,0 表示红色,1 表示蓝色。
输出格式
包含一个整数,最多能正确粉刷的格子数。
输入输出样例 #1
输入 #1
3 6 3
111111
000000
001100
输出 #1
16
说明/提示
\(30\%\) 的数据,满足 \(1 \le N,M \le 10,0 \le T \le 100\) 。
\(100\%\) 的数据,满足 \(1 \le N,M \le 50,0 \le T \le 2500\)
题意概括
给定 N 条木板,每条木板有 M 个格子,每个格子的正确颜色(红色或蓝色,用字符串表示:'0' 为红色,'1' 为蓝色)。以及最多粉刷次数 T。
每次粉刷操作:选择一条木板上一段连续格子,涂上一种颜色(红色或蓝色),每个格子最多被粉刷一次。
目标:通过最多 T 次操作,最大化正确粉刷的格子数(即粉刷后颜色与正确颜色匹配的格子数量,未粉刷或颜色不匹配的格子均算错误)。
思路
这里出现了粉刷 \(T\) 次的限制条件,这限制了操作次数,那么很明显这会作为dp的一维状态,再加上一共 \(n\) 行,题目又说是横着刷格子,所以说可以联想到:
设 \(f_{i,j}\) 指前 \(i\) 行中刷了 \(j\) 次的最大正确粉刷格子数,那么转移方程很容易得出:
其中 \(g_{i,k}\) 指第 \(i\) 行刷 \(k\) 次的最大格子数,那么现在很明显需要预处理出来第 \(i\) 行的最大格子数
可以考虑设 \(h_{i,l,r,j}\) 指第 \(i\) 行 \([l,r]\) 之间刷 \(j\) 次最多能刷正确的格数,则转移方程如下:
然后又可以发现这里时间复杂度爆炸了。
当遇到这种区间枚举存储不能接受的时候应该要想到能不能通过前缀后缀的方式,即固定区间左右端点再进行枚举,这样能少一维,最后其实可以发现并不需要 \(l,r\) 两个维度,只需要维护前 \(p\) 个值的对应答案就可以了,因此优化这里的状态设计及其转移:
设 \(h_{i,j,k}\) 指第 \(i\) 行前 \(j\) 个格子刷 \(k\) 次最多能刷正确的最多格子数,则转移方程如下:
那么上文所说的 \(g_{i,k}\) 其实就可以直接得出是 \(h_{i,m,k}\) 了
时间复杂度 \(O(nm^2T)\) 理论上应该过得很卡,但实际跑得飞快?

浙公网安备 33010602011771号