算法快學筆記(十六):動態規劃

1. 介紹

前文提到,對於揹包問題與旅行商問題,計算的複雜度是隨着計算數據的增加呈現指數級增長的,貪婪算法算可以處理,但得到的並不是最優解。

動態規劃的主要思路是先解決子問題,在逐步解決大問題。本文將通過兩個例子介紹動態規劃的推算思路。

2. 揹包問題

2.1 思路

通過動態規劃方法解決揹包問題的流程如下:

  1. 準備一個表格,商品作爲Y軸,揹包重量作爲x軸

  2. 使用下面的公式算出價格且更新到表格裏
    在這裏插入圖片描述

  3. 使用方法2,逐行填充表格,直到將表格填滿。

2.2 推算過程

用於推算的數據如下:

  1. 小偷的揹包可以放4KG的物品
  2. 可偷物品的價格,重量如下:
物品 重量 價值
吉他 1kg 1500
音響 4kg 3000
筆記本 3kg 2000
手機 1kg 2000

詳細推算過程如下:

  1. 初始化表格如下
* 1 2 3 4
吉他
音響
筆記本
手機
  1. 吉他是第一個商品,且重量只有1kg,則對於不同大小的揹包而言都可以放得下,所以第一行的值都爲1500
* 1 2 3 4
吉他 1500 1500 1500 1500
音響
筆記本
手機
  1. 音響是第二個商品,對於1,2,3三個揹包都放不下,所以能放的物品價值還是1500,第四個揹包可以放下,使前面提到的公式推導一下。
  • CELL[1][4]=1500
  • 當前價值+剩餘空間價值=3000+0(沒有剩餘的空間,所以剩餘價值爲0)
    通過上面的推算,可知音響這行最後一格的值爲3000
* 1 2 3 4
吉他 1500 1500 1500 1500
音響 1500 1500 1500 3000
筆記本
手機
  1. 看下筆記本,前兩個揹包都放不下,從第三個開始。第三個揹包放完筆記本後價值爲2000,且比CELL[2,3]要大,所以該值更新爲2000
* 1 2 3 4
吉他 1500 1500 1500 1500
音響 1500 1500 1500 3000
筆記本 1500 1500 2000
手機

再來看筆記本的最後一格,比較下面的值:

  • CELL[2][4]=3000
  • 2000(筆記本價格)+1500(剩餘空間的最大價值)=3500

由上可得出筆記本第四格的價值應該是3500

* 1 2 3 4
吉他 1500 1500 1500 1500
音響 1500 1500 1500 3000
筆記本 1500 1500 2000 3500
手機
  1. 手機的重量爲1kg.且比吉他的價格要貴,所以第一格替換成手機的價格
* 1 2 3 4
吉他 1500 1500 1500 1500
音響 1500 1500 1500 3000
筆記本 1500 1500 2000 3500
手機 2000

對於第二格,比較下面的值:

  • CELL[3][2]=1500
  • 2000(筆記本價格)+1500(剩餘空間的最大價值,C[3,1])=3500

由上可得出手機第二格的價值應該是3500

* 1 2 3 4
吉他 1500 1500 1500 1500
音響 1500 1500 1500 3000
筆記本 1500 1500 2000 3500
手機 2000 3500

第三格的推算過程與第二格類似,值同樣爲3500.

* 1 2 3 4
吉他 1500 1500 1500 1500
音響 1500 1500 1500 3000
筆記本 1500 1500 2000 3500
手機 2000 3500 3500

對於第四格,比較下面的值:

  • CELL[3][4]=3500
  • 2000(筆記本價格)+2000(剩餘空間的最大價值,C[3,3])=4000

由上可得出手機第四格的價值應該是4000

* 1 2 3 4
吉他 1500 1500 1500 1500
音響 1500 1500 1500 3000
筆記本 1500 1500 2000 3500
手機 2000 3500 3500 4000

最終可得知,小偷最多可偷4000元的商品,且偷的商品是手機+筆記本電腦。

2.4 其他注意事項

  1. 最終的結果和表格中商品的順序沒有關係
  2. 如果可偷的商品爲0.5kg. 則x軸的粒度要爲0.5。既0.5->1->1.5->2…
  3. 選擇商品的時候,每個商品都是獨立選擇的,不存在依賴關係。例如不應該出現選擇商品A,則必須(不能)選擇B的情況
  4. 最優解可能會導致最終的揹包沒有被裝滿

3. 最長公共子串

最場公共子串求出的是兩個字符串都包含的最長子串,例如:對於hish與fish兩個單詞,ish就是他們的最長公共子串。

3.1 思路

可以用解決揹包問題的思路來解決該問題,兩個單詞分別對應縱/橫軸,將公共子串的長度填到方格里,最後所有格子裏最大的值就是最大的公共子串的長度,連續從0到最大長度值對應的縱/橫軸對應的字母就是最長公共子串。

格子裏值的推算公式如下:

if word_a[i] == word_b[j]:
    cell[i][j] = cell[i-1][j-1] + 1
else:
    cell[i][j] = 0

在這裏插入圖片描述

按照上面的公式推算,FISH與HISH的結果如下:

在這裏插入圖片描述

既最大長度爲3,對應的子串爲ISH.

3.2 最長公共子序列

最長公共子序列:兩個單詞中都有的序列包含的字母數,最後求得的子序列長度越長,說明兩個單詞越相似

算法的步驟如下:
在這裏插入圖片描述

計算FOSH與FISH與FORT兩個單詞的最長公共子序列的過程與結果如下:

在這裏插入圖片描述

通過上述結果可看出,FISH與FOSH更像一些。

4. 總結

動態規劃的實際應用包括如下場景:

  • 生物學家根據最長公共序列來確定DNA鏈的相似性,進而判斷度兩種動物或疾病有多相似。

  • 前面討論了字符串的相似程度。 編輯距離( levenshtein distance)指出了兩個字符串的相
    似程度,也是使用動態規劃計算得到的。編輯距離算法的用途很多,從拼寫檢查到判斷用戶上傳的資料是否是盜版,都在其中。

  • Microsoft Word等具有斷字功能的應用程序,使用動態規劃確定在什麼地方斷
    字以確保行長一致。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章