这两天特别丧,不想学习,心态有点崩。不知道为什么,可能是假期综合症吧,又感觉自己处在了一种极度的迷茫之中,都怪袁老,让我自己一天吃饱了没事干,胡思乱想,呜呜呜.jpg。
区间DP
区间DP就是在区间上的动态规划,求解一段区间上的最优解,通过合并小区间的最优解来得到整个大区间上的最优解的算法。
时间复杂度一般为O(n^2)或者O(n^3),一般做法就是:
石子合并问题
很多人一看到石子合并问题可能会想到博弈论,但是博弈论上的一般是先手问题。而石子合并合并的一般是合并相邻两堆石子的数量。石子合并问题有两种玩法。操场玩法和路边玩法,操场玩法就是指把石子围成一堆,路边玩法就是把石子摆成一条直线。
贪心法不能解决,贪心法要求无后效性,但是条件为必须合并相邻两堆这个条件,贪心法无法保证每次都能取到所有堆中石子数最少的两堆。如6 3 4 6 5 4 2贪心法的最小值是62,但是实际上最小值为61,很明显贪心算出来的并不是最小值,贪心法在子过程中得到的解只是局部最优,而不能保证全局的值最优,因此本问题不可以使用贪心法求解。如果使用暴力穷举的办法,会有大量的子问题重复,这种做法会造成效率的低下,所以我们可以考虑动态规划法,是否具有最优子结构性质。
(1)分析最优解的结构特征。
假设已经知道了第k堆石子分开可以得到最优解,那么原问题就变成了两个子问题,子问题分别是{ai,a2,……,ak}和{ak+1,aj}原问题的最优解是否包含子问题的最优解呢?
假设已经知道了n堆石子合并起来的花费是c,子问题1{ai,a2,……,ak}和{ak+1,……,aj}石子合并起来的花费是b,{a1,a2,……,aj}石子数量之和是w(i,j)那么c=a+b+w(i,j).因此我们只需要证明c是最优的,则a和b一定是最优的(即原问题的最优解包含子问题的最优解)。证明用反证法来证。
(2)建立最优值递归式。
设dp[i][j]代表从第i堆到第j堆石子合并的最小花费,dp[i][k]代表从第i堆石子到第k堆石子合并的最小花费,dp[k+1][j]代表从第k+1堆石子到第j堆石子合并的最小花费。w(i,j)代表从第i堆到第j堆的石子数量之和。
dp[i][j]=0 i=j // min(dp[i][k]+dp[k+1][j]+w(i,j) i 题目 51Nod - 1021 N堆石子摆成一条线。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价。计算将N堆石子合并成一堆的最小代价。 例如: 1 2 3 4,有不少合并方法 1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19) 1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24) 1 2 3 4 => 1 2 7(7) => 3 7(10) => 10(20) 括号里面为总代价可以看出,第一种方法的代价最低,现在给出n堆石子的数量,计算最小合并代价。 Input 第1行:N(2 <= N <= 100) Output 输出最小合并代价 Sample Input Sample Output 这就是区间dp石子问题的常规解法,如果石子长度不长的话一般直接用dp来做,复杂度为O(n ^ 3), 但是这种方法时间复杂度并不低,在对时间有明显要求的时候这种方法不适合使用,这时候就要用到了一中新算法,叫(GarsiaWachs算法) 能把复杂度降到O(n ^ 2)甚至O(nlogn); 设序列是stone[],从左往右,找一个满足stone[k-1] <= stone[k+1]的k,找到后合并stone[k]和stone[k-1],再从当前位置开始向左找最大的j,使其满足stone[j] > stone[k]+stone[k-1],插到j的后面就行。一直重复,直到只剩下一堆石子就可以了。在这个过程中,可以假设stone[-1]和stone[n]是正无穷的。 举个例子: 假设石子的序列为100,45, 67, 200, 78; 那么第一次找的时候找到了67, 因为200 > 45, 然后合并为 112, 往前遍历,插到第一个比它大的值后面即stone[-1], 然后变成了112, 100, 200, 78, 继续操作, 然后合并112, 100为 212, 序列变为212 200 78, 记得stone[n]为无穷哦, 然后合并200, 78为278, 变为278, 212, 最后在合并为490 所以结果为112 + 212 + 278 + 490 = 1092。这种算法我还不是很会,呜呜呜,等我学会了再说。 圆型石子合并经常转换为直线型来求,也就是说,把圆形结构看成是长度为原规模两倍的直线结构来处理。如果操场玩法(直线玩法)原问题规模为n,所以就相当于有一排石子a1,a2,……,an-1.该问题规模为2*n-1,然后就可以用线性的石子合并问题来解决。石子归并
第2 - N + 1:N堆石子的数量(1 <= A[i] <= 10000)4
1
2
3
4
19
#include
它的步骤如下: