文章目录
- 区间DP 解题报告
- PKU 3186 Treats for the Cows
- PKU 3042 Grazing on the Run
- HDU 4745 Two Rabbits
- HDU 4521 吉哥系列故事——完美队形I
- HDU 4632 Palindrome subsequence
- PKU 1651 Multiplication Puzzle
- HDU 5115 Dire Wolf
- HDU 5396 Expression
- PKU 1179 Polygon
- HDU 5151 Sit sit sit
- HDU 4283 You Are the One
- PKU 2176 Folding
- PKU 1390 Blocks
- HDU 3427 Clickomania
- HDU 5693 D Game
- HDU 5900 QSC and Master
区间DP 解题报告
PKU 3186 Treats for the Cows
链接:PKU 3186 Treats for the Cows
题意:给定 n ( n ≤ 2000 ) n( n \le 2000) n(n≤2000) 个数 x i x_i xi,并且初始化 a = 1 a=1 a=1,每次可以从左右两边选择一个数和 a a a 相乘,然后 a = a + 1 a=a+1 a=a+1,直到所有数都执行完毕,问得到的最大乘积和是多少。
- 假设当前的左右区间为 i i i 和 j j j,并且执行完毕后得到的最大乘积和为 f [ i ] [ j ] f[i][j] f[i][j],那么接下来要么选择 i i i 要么选择 j j j,且这时候 a = n − ( j − i ) a = n - (j-i) a=n−(j−i),那么选择 i i i 的结果就是:
- c h o o s e i = f [ i + 1 ] [ j ] + ( n − j + i ) ∗ x i choose_i = f[i+1][j] + (n-j+i) * x_i choosei=f[i+1][j]+(n−j+i)∗xi
- 而选择 j j j 的结果则是:
- c h o o s e j = f [ i ] [ j − 1 ] + ( n − j + i ) ∗ x j choose_j = f[i][j-1] + (n-j+i) * x_j choosej=f[i][j−1]+(n−j+i)∗xj
- 对两种抉择,选择大者,状态转移方程:
- f [ i ] [ j ] = m a x ( c h o o s e i , c h o o s e j ) f[i][j] = max(choose_i, choose_j) f[i][j]=max(choosei,choosej)
- 其中边界条件为: f [ i ] [ i − 1 ] = 0 f[i][i-1] = 0 f[i][i−1]=0;
PKU 3042 Grazing on the Run
链接:PKU 3042 Grazing on the Run
题意:给定 n ( n ≤ 1000 ) n( n \le 1000) n(n≤1000) 个位置 x i x_i xi,并且一个起始点 s s s,从 s s s 出发往左右两边行进,计时器 t = 0 t = 0 t=0,每走一步 t = t + 1 t = t + 1 t=t+1,令尚未到达的点为 T T T,初始化为 n n n,每到达一个 x i x_i xi,累加消耗为 T ∗ t T * t T∗t,并且执行 T = T − 1 T=T - 1 T=T−1, t t t 归零;问所有位置都遍历完毕以后的最少消耗。
- 令 f [ i ] [ j ] [ 0 ] f[i][j][0] f[i][j][0] 为 第 i i i 个位置到第 j j j 个位置都遍历完毕,并且最后落在 x i x_i xi 的最少消耗; f [ i ] [ j ] [ 1 ] f[i][j][1] f[i][j][1] 为 第 i i i 个位置到第 j j j 个位置都遍历完毕,并且最后落在 x j x_j xj 的最少消耗;
- 当前尚未到达的点记为 y y y,则 y = n − ( j − i ) y = n-(j-i) y=n−(j−i);
- 则容易得到两个状态转移方程如下:
- f [ i ] [ j ] [ 0 ] = m i n ( ( x i + 1 − x i ) ∗ y + f [ i + 1 ] [ j ] [ 0 ] , ( x j − x i ) ∗ y + f [ i + 1 ] [ j ] [ 1 ] ) f[i][j][0] = min((x_{i+1}-x_{i})*y + f[i+1][j][0], (x_j-x_i)*y + f[i+1][j][1]) f[i][j][0]=min((xi+1−xi)∗y+f[i+1][j][0],(xj−xi)∗y+f[i+1][j][1])
- f [ i ] [ j ] [ 1 ] = m i n ( ( x j − x j − 1 ) ∗ y + f [ i ] [ j − 1 ] [ 1 ] , ( x j − x i ) ∗ y + f [ i ] [ j − 1 ] [ 0 ] ) f[i][j][1] = min((x_{j}-x_{j-1})*y + f[i][j-1][1], (x_j-x_i)*y + f[i][j-1][0]) f[i][j][1]=min((xj−xj−1)∗y+f[i][j−1][1],(xj−xi)∗y+f[i][j−1][0])
- 边界条件 f [ i ] [ i ] 0 ] = f [ i ] [ i ] [ 1 ] = ( s − x i ) ∗ n f[i][i]0] = f[i][i][1] = (s - x_i) * n f[i][i]0]=f[i][i][1]=(s−xi)∗n
HDU 4745 Two Rabbits
链接:HDU 4745 Two Rabbits
题意:给定一个 n ( n ≤ 1000 ) n( n \le 1000) n(n≤1000) 个元素 a i a_i ai 的序列围成一个环形,求最长的回文子序列的长度。
- 首先,不考虑环的情况,令 f [ i ] [ j ] f[i][j] f[i][j] 为第 i i i 个元素到第 j j j 个元素的最长回文子序列的长度,那么可以得出状态转移方程如下:
- f [ i ] [ j ] = { 0 i > j 1 i = j max { f [ i + 1 ] [ j − 1 ] + 2 f [ i + 1 ] [ j ] f [ i ] [ j − 1 ] i < j , a i = a j max ( f [ i + 1 ] [ j ] , f [ i ] [ j − 1 ] ) i < j , a i ≠ a j f[i][j] = \begin{cases}0 & i > j \\ 1 & i=j \\ \max \begin{cases} f[i+1][j-1] + 2 \\ f[i+1][j] \\ f[i][j-1] \end{cases} & i < j, a_i = a_j\\ \max(f[i+1][j], f[i][j-1]) & i < j, a_i \neq a_j \end{cases} f[i][j]=⎩⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎧01max⎩⎪⎨⎪⎧f[i+1][j−1]+2f[i+1][j]f[i][j−1]max(f[i+1][j],f[i][j−1])i>ji=ji<j,ai=aji<j,ai=aj
- 由于是环形,所以最后的答案是: max i = 1 n ( f [ 1 ] [ i ] , f [ i + 1 ] [ n ] ) \max_{i=1}^n(f[1][i], f[i+1][n]) maxi=1n(f[1][i],f[i+1][n])
HDU 4521 吉哥系列故事——完美队形I
链接:HDU 4521 吉哥系列故事——完美队形I
题意:给定 n ( n ≤ 200 ) n(n \le 200) n(n≤200) 个元素的序列 a i a_i ai,求它的最长单调回文子序列。
- 思路比较简单,直接用 f [ i ] [ j ] f[i][j] f[i][j] 表示两端分别为 a i a_i ai 和 a j a_j aj 的最大回文长度;
- 如果 a i ≠ a j a_i \neq a_j ai=aj,则 f [ i ] [ j ] = I N V A L I D f[i][j] = INVALID f[i][j]=INVALID;
- 否则, f [ i ] [ j ] = max x = i + 1 j − 1 ( 2 + d p [ x ] [ k ] ∣ k = e x t [ x ] [ j − 1 ] ) f[i][j] = \max_{x=i+1}^{j-1}( 2 + dp[x][k] | k = ext[x][j-1] ) f[i][j]=maxx=i+1j−1(2+dp[x][k]∣k=ext[x][j−1])
- 其中 e x t [ i ] [ j ] ext[i][j] ext[i][j] 表示 a [ i : j ] a[i:j] a[i:j] 中,和 a i a_i ai 相等的最大下标;
HDU 4632 Palindrome subsequence
链接:HDU 4632 Palindrome subsequence
题意:给定一个长度为 n ( n ≤ 1000 ) n(n \le 1000) n(n≤1000) 的字符串 s,求它的回文子序列的个数。
- 其实看到 1000 1000 1000,基本上就是 O ( n 2 ) O(n^2) O(n2) 的算法了,计数问题大多是 DP,但是用 f [ i ] [ j ] f[i][j] f[i][j] 无法表示状态的时候,我们可以考虑再多一个维度,这个维度应该是常数维度。
- 可以这么考虑:
- 用 f [ i ] [ j ] [ 4 ] f[i][j][4] f[i][j][4] 表示区间 [ i , j ] [i,j] [i,j] 的回文串计数方案,其中第三维的含义如下:
00 左右都不包含
01 包含右端点
10 包含左端点
11 左右端点都包含
- 对于区间 [ i , j ] [i,j] [i,j],对这四种情况进行分类讨论:
- 1)当左右端点都不包含的时候,方案数为: ∑ k = 0 3 f [ i + 1 ] [ j − 1 ] [ k ] \sum_{k=0}^{3}f[i+1][j-1][k] ∑k=03f[i+1][j−1][k];
- 2)当只包含右端点的时候,方案数为: f [ i + 1 ] [ j ] [ 1 ] + f [ i + 1 ] [ j ] [ 3 ] f[i+1][j][1] + f[i+1][j][3] f[i+1][j][1]+f[i+1][j][3];
- 3)当只包含左端点的时候,方案数为: f [ i ] [ j − 1 ] [ 2 ] + f [ i ] [ j − 1 ] [ 3 ] f[i][j-1][2] + f[i][j-1][3] f[i][j−1][2]+f[i][j−1][3];
- 4)当左右端点都包含的时候,必须满足 s i = s j s_i = s_j si=sj,那么方案数就是 1 + ∑ k = 0 3 f [ i + 1 ] [ j − 1 ] [ k ] 1 + \sum_{k=0}^{3}f[i+1][j-1][k] 1+∑k=03f[i+1][j−1][k](注意这里的 1 代表只包含左右两端点的情况);否则方案数为 0;
- 然后进行递归计算即可,递归出口需要注意:
- f [ i ] [ i − 1 ] [ k ] = 0 f[i][i-1][k] = 0 f[i][i−1][k]=0
- f [ i ] [ i ] [ k ] = { 0 k = 0 , 1 , 2 1 k = 3 f[i][i][k] = \begin{cases}0 & k=0,1,2\\1 & k=3\end{cases} f[i][i][k]={01k=0,1,2k=3
PKU 1651 Multiplication Puzzle
链接:PKU 1651 Multiplication Puzzle
题意:给定一个 n ( 3 ≤ n ≤ 100 ) n(3 \le n \le 100) n(3≤n≤100) 个元素的序列 a [ i ] a[i] a[i],每删除一个元素,就会产生一定的消耗,消耗为它本身与相邻两数的乘积,首尾两个数不能删除,问将数字删除到只剩两个的时候,最小的消耗是多少。
- 题解:如果采用暴力枚举删除的思路,利用深度优先搜索遍历所有情况,得到的搜索树,第一层有 n − 2 n-2 n−2 种选择,第二层有 n − 3 n -3 n−3 种选择,最后一层有一种选择,整个算法的时间复杂度为 O ( n ! ) O(n!) O(n!),当 n = 5 n=5 n=5 的搜索树如下图所示(其中数字代表下标):
- 可以发现有很多重复的计算,比如 [125]、[135]、[145] 都被计算了两次,搜索和动态规划的区别就是动态规划能够把一些子问题计算出来以后存起来,下次要用到的时候直接返回,无需重复计算。
- 对于一个序列,最后一定会经过 n − 2 n-2 n−2 次删除数字变成只剩下首尾两个数的情况,即:
- 那么我们考虑,如果最后一个被删除的数是 a [ k ] a[k] a[k],情况如下:
- 也就是说,如果最后一个被删除的是 a [ k ] a[k] a[k],那么消耗就是 a [ 1 ] ∗ a [ k ] ∗ a [ n ] a[1] * a[k] * a[n] a[1]∗a[k]∗a[n],那么对于 [ 1... k ] [1 ... k] [1...k] 和 [ k . . . n ] [k ... n] [k...n] 这两个区间,前者需要删除 k − 2 k-2 k−2 个数,后者需要删除 n − k − 1 n-k-1 n−k−1 个数,并且两个端点的数是不能被删除的。
- 这样就把原本大区间的问题,转换成了两个小区间的问题。
- 令 f [ i ] [ j ] f[i][j] f[i][j] 表示区间 [ i , j ] [i, j] [i,j] 中的数,删除除端点外的所有数得到的最小消耗,则有状态转移方程如下:
- f [ i ] [ j ] = { 0 j − i = 1 f [ i ] [ k ] + f [ k ] [ j ] + a [ i ] ∗ a [ k ] ∗ a [ j ] i < k < j f[i][j] = \begin{cases}0 & j-i=1\\ f[i][k] + f[k][j] + a[i]*a[k]*a[j] & i < k < j\end{cases} f[i][j]={0f[i][k]+f[k][j]+a[i]∗a[k]∗a[j]j−i=1i<k<j
- f [ 1 ] [ n ] f[1][n] f[1][n] 即为最后的答案,可以采用记忆化搜索求解。时间复杂度 O ( n 3 ) O(n^3) O(n3)。
HDU 5115 Dire Wolf
链接:HDU 5115 Dire Wolf
题意:在森林中有 n ( 3 ≤ n ≤ 200 ) n(3 \le n \le 200) n(3≤n≤200) 头狼排成一条直线,每个头狼有一个攻击力 a i a_i ai,以及一个附加攻击力 b i b_i bi,当一只狼被消灭,它将提供 【它本身的攻击力 + 相邻狼的附加攻击力】 的伤害,要求消灭所有的狼,求受到的最小伤害。
- 题解:令 f [ i ] [ j ] f[i][j] f[i][j] 表示第 i i i 头狼到第 j j j 头狼被消灭的最小伤害,考虑在这 j − i + 1 j-i+1 j−i+1 头狼中最后消灭的是第 k k k 头狼的情况,这时候,伤害为 : c o s t i , j , k = a k + b i − 1 + b j + 1 cost_{i,j,k} = a_k + b_{i-1}+b_{j+1} costi,j,k=ak+bi−1+bj+1,然后逐渐缩小区间即可,有状态转移方程:
- f [ i ] [ j ] = min k = i j ( f [ i ] [ k − 1 ] + f [ k + 1 ] [ j ] + c o s t i , j , k ) f[i][j] = \min_{k=i}^{j}(f[i][k-1] + f[k+1][j] + cost_{i,j,k}) f[i][j]=k=iminj(f[i][k−1]+f[k+1][j]+costi,j,k)
- 边界条件是: f [ i ] [ i − 1 ] = 0 f[i][i-1] = 0 f[i][i−1]=0
- 记忆化搜索求解即可。
HDU 5396 Expression
链接:HDU 5396 Expression
题意: n ( n ≤ 100 ) n (n \le 100) n(n≤100) 个数,每两个数中间有一个符号(’+’, ‘-’, ‘*’),每消掉一个符号就会通过这个符号计算出两边数的值,消去所有符号以后得到一个数 X。问所有可能产生的 X 的和模上 1 0 9 + 7 10^9 + 7 109+7 的和。
- 题解:例如这样的一个表达式:
- a 0 ∗ a 1 − a 2 + a 3 + a 4 + a 5 + a 6 a_0 * a_1 - a_2 + a_3 + a_4 + a_5 + a_6 a0∗a1−a2+a3+a4+a5+a6
- 我们在 a 3 a_3 a3 和 a 4 a_4 a4 中间断开,得到如下表达式:
- ( a 0 ∗ a 1 − a 2 + a 3 ) + ( a 4 + a 5 + a 6 ) (a_0 * a_1 - a_2 + a_3) + (a_4 + a_5 + a_6) (a0∗a1−a2+a3)+(a4+a5+a6)
- 我们发现左边有 3 3 3 个运算符,所以左边共有 3 ! = 6 3! = 6 3!=6 种运算结果;右边有 2 2 2 个运算符,所有右边共有 2 ! = 2 2! = 2 2!=2 种运算结果。
- 令左边的运算结果为: l 0 , l 1 , l 2 , l 3 , l 4 , l 5 l_0, l_1, l_2, l_3, l_4, l_5 l0,l1,l2,l3,l4,l5,右边的运算结果为 r 0 , r 1 r_0, r_1 r0,r1,在进行加法运算以后得到如下 12 种结果:
- l 0 + { r 0 r 1 l 1 + { r 0 r 1 l 2 + { r 0 r 1 l 3 + { r 0 r 1 l 4 + { r 0 r 1 l 5 + { r 0 r 1 l_0 + \begin{cases}r_0 \\ r_1\end{cases} \\ l_1 + \begin{cases}r_0 \\ r_1\end{cases} \\ l_2 + \begin{cases}r_0 \\ r_1\end{cases} \\ l_3 + \begin{cases}r_0 \\ r_1\end{cases} \\ l_4 + \begin{cases}r_0 \\ r_1\end{cases} \\ l_5 + \begin{cases}r_0 \\ r_1\end{cases} l0+{r0r1l1+{r0r1l2+{r0r1l3+{r0r1l4+{r0r1l5+{r0r1
- 总和为: S = ( l 0 + l 1 + l 2 + l 3 + l 4 + l 5 ) ∗ 2 + ( r 0 + r 1 ) ∗ 6 S = (l_0 + l_1 + l_2 + l_3 + l_4 + l_5) * 2 + (r_0 + r_1) * 6 S=(l0+l1+l2+l3+l4+l5)∗2+(r0+r1)∗6,这是组合的情况,再算上排列,为 S ∗ C 3 + 2 2 S * C_{3+2}^2 S∗C3+22;
- 减法也可以采用同样的计算方式。当中间断开的符号为 * 时,如下:
- ( a 0 ∗ a 1 − a 2 + a 3 ) ∗ ( a 4 + a 5 + a 6 ) (a_0 * a_1 - a_2 + a_3) * (a_4 + a_5 + a_6) (a0∗a1−a2+a3)∗(a4+a5+a6)
- 那么可以得到 12 种组合结果如下:
- l 0 ∗ { r 0 r 1 l 1 ∗ { r 0 r 1 l 2 ∗ { r 0 r 1 l 3 ∗ { r 0 r 1 l 4 ∗ { r 0 r 1 l 5 ∗ { r 0 r 1 l_0 * \begin{cases}r_0 \\ r_1\end{cases} \\ l_1 * \begin{cases}r_0 \\ r_1\end{cases} \\ l_2 * \begin{cases}r_0 \\ r_1\end{cases} \\ l_3 * \begin{cases}r_0 \\ r_1\end{cases} \\ l_4 * \begin{cases}r_0 \\ r_1\end{cases} \\ l_5 * \begin{cases}r_0 \\ r_1\end{cases} l0∗{r0r1l1∗{r0r1l2∗{r0r1l3∗{r0r1l4∗{r0r1l5∗{r0r1
- 总和为: S = ( l 0 + l 1 + l 2 + l 3 + l 4 + l 5 ) ∗ ( r 0 + r 1 ) S = (l_0 + l_1 + l_2 + l_3 + l_4 + l_5) * (r_0 + r_1) S=(l0+l1+l2+l3+l4+l5)∗(r0+r1),这是组合的情况,再算上排列,为 S ∗ C 5 2 S * C_5^2 S∗C52;
- d p [ i ] [ j ] dp[i][j] dp[i][j] 代表第 i i i 个数到第 j j j 个数中,中间的 j − i j-i j−i 个符号经过 ( j − i ) ! (j-i)! (j−i)! 次消除得到的所有结果之和,进行区间 DP,枚举每个符号最后一次被删除的两边结果的汇总。
PKU 1179 Polygon
链接:PKU 1179 Polygon
题意:给定一个 n ( n ≤ 50 ) n( n \le 50 ) n(n≤50) 个结点的多边形,多边形的顶点上是数字,边上是符号(+ 号和 *号),现在需要先删掉一条多边形的边,将多边形变成一条链,然后再把 n − 1 n-1 n−1 条边删掉,每删掉一条边就把边上连接的结点的数字通过符号组合成另一个数字,删完所有边就得到了最后一个数字,求使得这个数字最大的方案。
- 首先考虑非环形的情况, f m a x [ i ] [ j ] fmax[i][j] fmax[i][j] 表示第 i i i 个数到第 j j j 个数中间去掉所有符号后得到的最大值, f m i n [ i ] [ j ] fmin[i][j] fmin[i][j] 则代表最小值,考虑第 k k k 符号最后个删除的情况:
- 如果第 k k k 个符号为 ‘+’,则:
- f m a x [ i ] [ j ] = max k = i j − 1 ( f m a x [ i ] [ k ] + f m a x [ k + 1 ] [ j ] ) f m i n [ i ] [ j ] = min k = i j − 1 ( f m i n [ i ] [ k ] + f m i n [ k + 1 ] [ j ] ) fmax[i][j] = \max_{k=i}^{j-1}(fmax[i][k] + fmax[k+1][j]) \\ fmin[i][j] = \min_{k=i}^{j-1}(fmin[i][k] + fmin[k+1][j]) fmax[i][j]=k=imaxj−1(fmax[i][k]+fmax[k+1][j])fmin[i][j]=k=iminj−1(fmin[i][k]+fmin[k+1][j])
- 如果第 k k k 个符号为 ‘*’,则:
- f m a x [ i ] [ j ] = max k = i j − 1 ( f m a x [ i ] [ k ] ∗ f m a x [ k + 1 ] [ j ] , f m i n [ i ] [ k ] ∗ f m i n [ k + 1 ] [ j ] ) f m i n [ i ] [ j ] = min k = i j − 1 ( 四 种 相 乘 ) fmax[i][j] = \max_{k=i}^{j-1}(fmax[i][k] * fmax[k+1][j], fmin[i][k] * fmin[k+1][j]) \\ fmin[i][j] = \min_{k=i}^{j-1}(四种相乘) fmax[i][j]=k=imaxj−1(fmax[i][k]∗fmax[k+1][j],fmin[i][k]∗fmin[k+1][j])fmin[i][j]=k=iminj−1(四种相乘)
- 四种相乘即:最大 * 最大,最大 * 最小,最小 * 最大,最小 * 最小;
- 如果要求环的情况,只需要把数字和符号都复制一份,然后找 f m a x [ 0 ] [ n − 1 ] , f m a x [ 1 ] [ n ] , f m a x [ 2 ] [ n + 1 ] , . . . fmax[0][n-1],fmax[1][n],fmax[2][n+1],... fmax[0][n−1],fmax[1][n],fmax[2][n+1],... 中的最大值即可。
HDU 5151 Sit sit sit
链接:HDU 5151 Sit sit sit
题意:有 n ( n ≤ 100 ) n(n \le 100) n(n≤100)个空的椅子排成一排,椅子有两种颜色:红和蓝,每个椅子的颜色为 c o l o r i color_i colori, 然后来了一些小朋友,编号为 [ 1 , n ] [1, n] [1,n] ,对于每个小朋友,他会选择一个空的椅子坐上去,如果同时满足以下三个条件,那么他不会坐上去:
1)椅子左右两边都有相邻的椅子;
2)左右相邻椅子都非空;
3)左右相邻椅子颜色不同;
如果当前的学生不能找到一个椅子坐上去,他就会走掉;
请求出所有的方案数模上 1000000007。
- 主要有以下几个思路:
- 1)考虑前 j − i j-i j−i 个孩子占据了 [ i , k ) [i, k) [i,k) 和 ( k , j ] (k, j] (k,j] 个位置,那么只有当 c o l o r k − 1 = c o l o r k + 1 color_{k-1}=color_{k+1} colork−1=colork+1 时,第 j − i + 1 j-i+1 j−i+1 个孩子才能被放入到 第 k k k 个位置;
- 2)对于任意的 [ i , j ] [i, j] [i,j] 个位置,如果都没有被放置孩子,那么两个端点都可以被放置(无视颜色);
- 3)对于任意的 [ i , j ] [i, j] [i,j] 个位置,如果第 k k k 个位置能够被放入孩子,那么 [ i , k ) [i, k) [i,k) 个位置共有 c j − i k − i c_{j-i}^{k-i} cj−ik−i 种情况;
- 于是可以定义状态 f [ i ] [ j ] f[i][j] f[i][j] 表示第 i i i 个位置到第 j j j 个位置的孩子,按要求放置 [ 1 , j − i + 1 ] [1, j-i+1] [1,j−i+1] 号孩子的方案数;
- 有状态转移方程:
- f [ i ] [ j ] = ∑ k = i j c j − i k − i ∗ f [ i ] [ k − 1 ] ∗ f [ k + 1 ] [ j ] f[i][j] = \sum_{k=i}^{j} c_{j-i}^{k-i} * f[i][k-1] * f[k+1][j] f[i][j]=k=i∑jcj−ik−i∗f[i][k−1]∗f[k+1][j]
- 边界条件为 f [ i ] [ i ] = f [ i ] [ i − 1 ] = 1 f[i][i] = f[i][i-1] = 1 f[i][i]=f[i][i−1]=1;
HDU 4283 You Are the One
链接:HDU 4283 You Are the One
题意:有 n ( n ≤ 100 ) n(n \le 100) n(n≤100)个男士要进行相亲,并且按照一定顺序入场,每个人有个愤怒值 d i d_i di,如果他被规定为第 k k k 个入场,那么他的愤怒值就是 ( k − 1 ) ∗ d i (k-1) * d_i (k−1)∗di,但是现在有个先进后出的房间,可以让这些男士进入这个房间,从而改变他们原有的顺序,问如何才能使得总愤怒值最小,求这个最小值。
- 令 f [ i ] [ j ] f[i][j] f[i][j] 表示 从第 i i i 个男士到第 j j j 个男士进场完,得到的最小愤怒值。
- 那么,如果第 i i i个男士在第 k ( 1 ≤ k ≤ j − i + 1 ) k (1 \le k \le j-i+1) k(1≤k≤j−i+1) 个进场,他的愤怒值为 : ( k − 1 ) ∗ d i (k-1) * d_i (k−1)∗di;
- 则第 i + 1 → i + k − 1 i+1 \to i+k-1 i+1→i+k−1 必然在它前面入场,则这些愤怒值总和为 f [ i + 1 ] [ i + k − 1 ] f[i+1][i+k-1] f[i+1][i+k−1];
- 而 i + k → j i+k \to j i+k→j 这些人,由于前面已经有 k k k 个人进场,愤怒值需要加上 k ∗ ∑ s = i + k j d s k*\sum_{s=i+k}^{j} d_s k∗∑s=i+kjds
- 得到状态转移方程:
- f [ i ] [ j ] = ( k − 1 ) ∗ d i + f [ i + 1 ] [ i + k − 1 ] + f [ i + k ] [ j ] + k ∗ ∑ s = i + k j d s f[i][j] = (k-1) * d_i + f[i+1][i+k-1] + f[i+k][j] + k*\sum_{s=i+k}^{j} d_s f[i][j]=(k−1)∗di+f[i+1][i+k−1]+f[i+k][j]+k∗s=i+k∑jds
- 边界条件: f [ i ] [ i − 1 ] = 0 f[i][i-1] = 0 f[i][i−1]=0
PKU 2176 Folding
链接:PKU 2176 Folding
题意:给定一个字符串,可以对它的子串进行压缩,求压缩后的最短长度,例如 AAAAAAAAAABABABCCD 可以被压缩成 9(A)3(AB)CCD。
- 这题主要有三种情况:
- 1)没有任何压缩的字符串;
- 2)由两个压缩过的字符串合并而来的字符串: S = S ′ S ′ ′ S = S'S'' S=S′S′′;
- 3)本身是一个可压缩串, S = X ( S ′ ) S = X(S') S=X(S′);
- 加入一些字符串子串判断的预处理即可,当然最后回溯路径的时候不要用 STL 的 string, 老老实实写传统 c 字符串处理吧,PKU 卡 STL;
- 注意这题有嵌套,提供一组数据:
BAAAAABAAAAA
2(B5(A))
PKU 1390 Blocks
链接:PKU 1390 Blocks
题意: n ( n ≤ 200 ) n ( n \le 200 ) n(n≤200) 个方块排成一排,每个方块一种颜色,每次可以选择其中一种连续的颜色块进行消除,消除的分数为色块长度的平方,求最后全部色块消除的总分,要求这个最大值;
输入:9
1 2 2 2 2 3 3 3 1
输出:29 ( 4 2 + 3 2 + 2 2 ) (4^2+3^2+2^2) (42+32+22)
- 预处理输入,将相同颜色的方块归并, c o l o r i color_i colori 表示第 i i i 种方块的颜色, n u m i num_i numi 表示第 i i i 种方块的数量;
- 令 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k] 表示 [ i , j ] [i, j] [i,j] 消掉,并且第 j j j 个块连同后面 k k k 个块消去的最大分数;
- 1)第 j j j 个块单独和后面的 k k k 个块消掉,那么分数为 d p [ i ] [ j − 1 ] [ 0 ] + ( n u m j + k ) 2 dp[i][j-1][0] + (num_j+k)^2 dp[i][j−1][0]+(numj+k)2 ;
- 2)对于 s ∈ [ i , j ) s \in [i, j) s∈[i,j),如果 c o l o r s = c o l o r j color_s = color_j colors=colorj,则有:
- d p [ i ] [ s ] [ n u m j + k ] + d p [ s + 1 ] [ j − 1 ] [ 0 ] dp[i][s][ num_j + k ] + dp[s+1][j-1][0] dp[i][s][numj+k]+dp[s+1][j−1][0]
- 对 2)的解释:如果中间某个块 ( i n d e x = s ) (index = s) (index=s) 和最后的那个块 ( i n d e x = j ) (index = j) (index=j) 的颜色相同,那么如果我们要把他们在后续归并到一起,势必中间的 ( s , j ) (s, j) (s,j) 这块要单独计算,即 d p [ s + 1 ] [ j − 1 ] [ 0 ] dp[s+1][j-1][0] dp[s+1][j−1][0];并且,为 [ i , s ] [i,s] [i,s] 这个区间增加了 n u m j + k num_j + k numj+k 个和 i n d e x = s index=s index=s 的块的个数,即 d p [ i ] [ s ] [ n u m j + k ] dp[i][s][ num_j+k ] dp[i][s][numj+k];
- | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
颜色 | C3 | C2 | C4 | C2 | C4 |
个数 | 3 | 4 | 2 | 9 | 2 |
HDU 3427 Clickomania
链接:HDU 3427 Clickomania
基本就是抄的 PKU 1390
HDU 5693 D Game
链接:HDU 5693 D Game
题意:首先给定一个公差集合 D,然后依次写下 n ( n ≤ 300 ) n(n \le 300) n(n≤300) 个数字 a i a_i ai 排成一行。游戏规则很简单:
1、在当前剩下的有序数组中选择 x ( x ≥ 2 ) x(x \ge 2) x(x≥2) 个连续数字;
2、检查 1 中选择的 x x x 个数字是否构成等差数列,且公差 d ∈ D d \in D d∈D;
3、如果 2 满足,可以在数组中删除这 x x x 个数字;
4、重复 1−3 步,直到无法删除更多数字。
问最多能删除多少个数字。
- 题意:对于这个问题来说,假设某一次能够删掉 4 个数,那么一定可以把它分成两个区间,每个区间分别删掉 2 个;如果删掉 5 个数,那么一定可以把它分成两个区间,一个区间删掉 2 个,一个区间删掉 3 个;以此类推,任何大于 3 的情况,一定可以转化成删掉 2 个,或者删掉 3 个的子区间来求解。如图所示:
- 1)红色的 1 3 5 7 能够被删掉的情况和 1 3 与 5 7 分别被删掉的情况等价;这样就对应了区间拆分;
- 状态转移方程为: f [ i ] [ j ] = max k = i j f [ i ] [ k ] + f [ k + 1 ] [ j ] f[i][j] = \max_{k=i}^{j} f[i][k] + f[k+1][j] f[i][j]=maxk=ijf[i][k]+f[k+1][j]
- 2)并且 1 3 能够被删掉,那么中间的蓝色块必须都要被删掉;这样就对应了区间缩圈;
- 2.a)对于删掉三个数的情况,考虑左边 a i a_i ai,中间 a k a_k ak,右边 a j a_j aj 这三个数满足等差数列,并且中间段能够自行消除,所以条件为: f [ i + 1 ] [ k − 1 ] = = k − i − 1 f[i+1][k-1] == k-i-1 f[i+1][k−1]==k−i−1 且 f [ k + 1 ] [ j ] = = j − k f[k+1][j] == j - k f[k+1][j]==j−k,那么这整个区间都可以被删掉;
- 2.b)对于删掉两个数的情况,考虑左边 a i a_i ai 和 右边 a j a_j aj 这两个数满足等差数列,并且中间段能够自行消除,所以条件为: f [ i + 1 ] [ j − 1 ] = = j − i − 1 f[i+1][j-1] == j-i-1 f[i+1][j−1]==j−i−1,那么整个区间可以被删除;
HDU 5900 QSC and Master
链接:HDU 5900 QSC and Master
题意:给定 ( n ≤ 300 ) (n \le 300) (n≤300) 个 元素的数组,每个元素是个二元组 ( a i , b i ) (a_i, b_i) (ai,bi),每次可以从这堆元素中选出相邻两个 g c d ( a i , a i + 1 ) > 1 gcd(a_i, a_{i+1}) > 1 gcd(ai,ai+1)>1 的元素消掉,并且获得得分 b i + b i + 1 b_i + b_{i+1} bi+bi+1,直到消无可消,求最后得到的得分总和最大值。
- 分两种情况讨论:
- 1)切割小区间,那么就是 f [ i ] [ j ] = m a x ( f [ i ] [ j ] , f [ i ] [ k ] + f [ k + 1 ] [ j ] ) f[i][j] = max(f[i][j], f[i][k] + f[k+1][j]) f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]);
- 2)当前区间的端点两个元素 a l , a r a_l, a_r al,ar 作为最后被消去的元素,那么需要满足两个条件:
- 2.a) g c d ( a l , a r ) > 1 gcd(a_l, a_r) >1 gcd(al,ar)>1
- 2.b)区间 [ l + 1 , r − 1 ] [l+1, r-1] [l+1,r−1] 能够消去的最大和为 ∑ i = l + 1 r − 1 b i \sum_{i=l+1}^{r-1}b_i ∑i=l+1r−1bi
- 这种情况下 f [ i ] [ j ] = ∑ i = l r b i f[i][j] = \sum_{i=l}^{r}b_i f[i][j]=∑i=lrbi