题意
有一个长度为 n n n的序列,每次可以删掉一个连续的子序列,要求这个子序列相邻的两个数只能差 1 1 1,且每个不在两端的数不能同时小于它的相邻两数,删掉一个长度 l l l的子序列会获得对应的分数 v [ l ] v[l] v[l],求最大得分。
n ≤ 150 n\le 150 n≤150,相同的数不会超过 7 7 7个。
题解
根据题意和数据范围,考虑区间DP。发现最终删掉的数在原序列中也是一些连续的子序列,且状态记为一个区间部删掉是比较好做的,因此求出每个区间全部删掉的最大得分后再对全局DP一次。
但发现对于区间 [ l , r ] [l,r] [l,r],如果枚举删掉哪个子区间,剩下的又会合并在一起,是无法转移的。考虑剩下的两部分,左边可能利用右边的一些数,但这些数具体是什么,对左边DP值的计算是没有影响的,我们只需知道左边的数消的过程中,每一次需要用到右边的多少数。发现只需关心第一次用到后面的数即可,因为后面的就是转移到的状态考虑的事情了。
于是记 f [ l ] [ r ] [ k ] f[l][r][k] f[l][r][k]为 [ l ] [ r ] [l][r] [l][r]消完的最大得分,且在消的过程中第一次需要用到后面的数时,需要消掉后面的 k k k个数,并强制让第一次需要用到后面的数时, r r r在这个被消的序列上。
转移时,考虑 r r r上的数在它所在的被消掉的序列:如果它是第一个,那么直接由 f [ l ] [ r − 1 ] [ 0 ] + v [ k + 1 ] f[l][r-1][0]+v[k+1] f[l][r−1][0]+v[k+1]转移过来,否则枚举上一个比它大1/小1的数在哪(即它所在的被消掉的序列的上一个数),注意由于“每个不在两端的数不能同时小于它的相邻两数”的限制,要多记一个类似 f f f的 g g g代表最后两个一定不会递减的DP值。总效率是 O ( 7 × n 3 ) O(7\times n^{3}) O(7×n3)。
特别地,对 f [ l ] [ r ] [ 0 ] f[l][r][0] f[l][r][0],需要由 f [ l ] [ i ] [ 0 ] + f [ i + 1 ] [ r ] [ 0 ] f[l][i][0]+f[i+1][r][0] f[l][i][0]+f[i+1][r][0]来更新,因为两个相邻的连续子序列各自删掉后,没有相互依赖的关系,不会在上面的转移中合并。