题意简述
一个$n\times m$的矩阵,每个位置珂能是粉色(0表示)或者是蓝色(1表示),然后你珂以对同一行里连续一段长度的区间染上一种颜色(覆盖型),你能染$t$次,每次不限长度。求你染到的正确的颜色的个数最多是多少。
思路框架
$f[i][j]$表示前$i$行染$j$次最大染色个数。$g[i][j][k]$表示第$i$行染$j$次只考虑前$k$个格子最大方案。
具体思路
$DP$题分两步,设状态,求转移。
多数题目是状态不好设的。像这个题就是,我想了好久没想出来状态怎么设,看一下题解知道状态怎么设之后就是秒切。那么,我们这个题也是分两块来讲。
Part 1. 状态
首先$f$是很好想的。答案就是$f[n][i] (i\in [1,t])$中的最大值。
然后我们来求$f[i][j]$的转移。求着求着发现,我们先要枚举一个$k$,$k$小于$j$。转移的一部分就是$f[n-1][j-k]$,就是上一行染$j-k$次。还有$k$次留给这一行。所以我们要加上一个数,这个数就是:第$i$行中染$k$次正确染色的最大值。
然后我们来求这个子问题。
Part 1.1 子问题的状态
设$g[i][j]$表示第$i$行染$j$次的答案。考虑转移。。。转你妈,缺状态。观察数据也能轻易发现,应该是$O(nmt)$的算法,然后$O(nt)$过是什么鬼,肯定还缺一维。
缺什么状态呢。我们发现,还和染到了那里有关。不妨再加上一个$k$,表示我们考虑到第$k$个位置。
Part 1.2 子问题的转移
然后就来推转移了。像这种有“考虑到第xxx个位置”为一个状态的$DP$,通常我们用枚举断点作转移。枚举断点$q$(我真的没名字了,$i,j,k$都用过了,就叫$q$了,随便一点)。由定义,$q$小于$k$。还有一个注意点,$q$是能取$0$的。其原因是,我习惯枚举的是$q$把区间分成$[0,q]$和$[q+1,k]$。显然,$q$取$0$时也有意义。
然后我们要看$[q+1,k]$中是蓝色多还是粉色多,哪个多我们就染那种颜色。这样显然是对的。然后我们只要维护一个前缀和出来,维护每一行内蓝色的前缀和,记为$sum$。看是 $sum[i][k]-sum[i][q]$大,还是$(k-q)-(sum[i][k]-sum[i][q])$大。设这两个的最大值为$S$。
那么$g[i][j][k]=max(g[i][j-1][q]+S)$。
Part 1.3 时间复杂度?
看起来状态数是$O(nmt)$,转移数是$O(m)$,复杂度$O(nm^2t)$。但是,$g$的第二维,即染了$j$次那一维中,显然$j$不会超过$m$。因为这一行最多就$m$个数,染$m$次啥事都解决了。所以复杂度应该是$O(nm^3)$,即$O(50^4)$。稳过。
子问题完毕
Part 2. 转移
好了,回到主线。有了$g$之后,就珂以得到$f$的转移:
$f[i][j]=max(f[i-1][j-k]+g[i][k][m]) $(哎哟这个式子不要太显然,我真的不想解释了)
($Part2$比$Part1$短很多,说明这个题重点在设状态,是个毒瘤题)
代码 (精髓)
1 |
|