动态规划概念:
就是将一个问题不断的缩小,缩小到子问题,然后得出子问题的解,再有子问题的解求出父问题的解,一步一步最终得到答案。
动态规划的核心:求解递推表达式
动态规划与贪心法的区别:
可以说贪心法是动态规划的一种特例,贪心是每次取得最优值,再用这个值进行下一步计算,而动态规划多了一部回溯,即我当前的问题的解,是需要前面已解决问题的解中的某个解。
譬如在最长公共上升子序列中,dp[i] = a[i]+ max(dp[i])[ 0< j < i]
再如背包问题 dp [ I ][ j ] = max(dp[I-1] [j – weight[i]] + value[i], dp[i-1][j]),都是需要回溯到前面某个状态,而不一定是直接子状态。
动态规划的类型题目:
1). 0-1背包问题:
有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?
核心:每个物品可取可不取,不取,则直接继承上一背包状态dp[i-1][j]; 取,则背包必须容得下这物品,所以背包重量必须 j - weight[i], 达到放入的条件。最后取价值最高的
递推方程:dp [ I ][ j ] = max(dp[I-1] [j – weight[i]] + value[i], dp[i-1][j])
2) 最长公共子序列:
给定两个字符串,求解这两个字符串的最长公共子序列(Longest Common Sequence)。比如字符串1:BDCABA;字符串2:ABCBDAB
则这两个字符串的最长公共子序列长度为4,最长公共子序列是:BCBA
核心: 我们每次都记录到此字符a[I]为字串结尾时,最长的结果。那么我们就从a[0~i-1]之中找比a[i] 小的字符,以此字符结尾的字串也必定小于a[I], 而以a[j] 结尾的字串的结果保存于dp[j] 中,所以在只要找到最大的dp[j] 就可以了。
递推公式:dp[i] = a[i]+ max(dp[i])[ 0< j < i]
3) 有向无环图动态规划:
在一个地图上有n个地窖(n≤200),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径,并规定路径都是单向的,且保证都是小序号地窖指向大序号地窖,也不存在可以从一个地窖出发经过若干地窖后又回到原来地窖的路径。某人可以从任意一处开始挖地雷,然后沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使他能挖到最多的地雷。
核心: 这种题最好的办法就是用图来存储所有节点的·情况,而且根据题意,这个题是有向无环图。题中,我们得知,当我以节点n【i】为结尾是,到他位置的最长路径,是与n【i】有链接关系的节点有关的,而且题目也说节点一定是小的接着大的,所以当前节点的前状态必然已算,所以:dp[i] = max(dp[j]) + n[i];
要记住的是,最终结果并不在dp【max】取得,而是某个dp值取得,所以还要算dp最大值。
其实动态规划的题目很多,而且多变,很难把握,再者动态规划不算一种算法,更更多的是一种思想,还是要多打题,慢慢领悟。