数据结构与算法-动态规划(2)

3/8/2017来源:ASP.NET技巧人气:1214

继续讲上次的故事: 皇帝回到宫中,越想心里越没底,“这帮老官僚,又不知道要怎么糊弄朕”,于是,他叫来了两个贴身宦官,小周子,小俊子。 “小俊子,你给朕算算,这10座金矿的事,要是每种情况都去算,要派多少人去算啊” “启禀陛下,10座金矿,每座矿有两种可能(挖或者不挖),那就是2的10次方,一共1024种可能性” “小周子,那你给朕算算,如果用朕的方法,这帮官僚要动用多少人啊” “启禀陛下,您的算法,一共是(1+2+4+8+16+32…+512)1023种可能性” 皇帝心里一惊,敢情我的办法也没有多好,正在踌躇之际,小周子又发话了:“这1023种可能性,并不需要1023个人去算的” “哦?此话怎讲?”

现在我们假设 如果每个金矿需要的人数是一样的 都为1000人 来看一个表 皇帝(10000,10) 左丞(9000,9) 右丞(10000,9) 左丞左尚书(8000,8) 左丞右尚书(9000,8) 右丞左尚书(9000, 8) 右丞右尚书(1000,8)

到这里,各位看官有没有发觉一个问题,其实左丞右尚书和右丞左尚书要解决的问题,是同一个,都是9000个人去挖1~8号矿,最多能挖出多少,这就是一个重复计算的问题。这里牵扯出动态规划的第三个特性

备忘录 从刚才的故事里可以看出,如果在动态规划的计算过程中,如果每个问题我们都去计算的话,动态规划的效率不比穷举法要好多少。因此,需要把计算过的结果做号存储,在下一次遇到相同问题时,直接获得结果,而不是去重复计算。

动规的一般思路 – 将原问题分解为子问题 把原问题分解为若干个子问题,子问题和原问题形式相同或类似,只不过规模变小了。子问题都解决,原问题即解决 – 确定状态 在用动态规划解题时,我们往往将和子问题相关的各个变量的一组取值,称之为一个“状 态”。一个“状态”对应于一个或多个子问题, 所谓某个“状态”下的“值”,就是这个“状 态”所对应的子问题的解。 所有“状态”的集合,构成问题的“状态空间”。“状态空间”的大小,与用动态规划解决问题的时间复杂度直接相关。 – 确定边界值 不要把底层的县令给忘了 – 确定状态转移方程 定义出“状态”,以及该“状态”下的“值”,找出不同的状态之间如何迁移,求出另一个“状态”的“值”。状态的迁移可以用递推公式即状态转移方程。

能用动规解决的问题的特点 – 问题具有最优子结构性质:如果问题的最优解所包含的子问题的解也是最优的。 –无后效性:当前的若干个状态值一旦确定,则此后过程的演变就只和这若干个状态的值有关,和之前是采取哪种手段或经过哪条路径演变到当前的这若干个状态没有关系。