寫在最前面,在寫第七章之前,我以前在上算法課的時候也總結過一篇關於動態規劃的文章,這次的總結也算是複習+學習新知,側重點變成了算題。動態規劃很多時候需要的是一種思想,一種能察覺到問題具有最優子結構,然後通過分析得到遞推關係式的過程。而很多問題的最優子結構性質如果是剛接觸過一般難以在短時間內解決,所有還是鼓勵平時多算題,多積累,說不定哪天考場上就出現了你碰過的題目了呢,
1.遞推求解
跳臺階[推導,得到類似於斐波那契的遞推關係式]
不容易系列之一(九度教程第 94 題)
需要通過數學推導得到錯排公式
2.最長遞增子序列
對於LIS問題可以得到如下遞推公式:
其中F[i]表示以第i個字符結尾的最長遞增(後面的元素必須大於前面的元素,不能是等於)子序列的長度。
其實寫到這裏我想說的是,上面給的遞推方程是錯的!沒錯,你沒看錯,是錯的,錯的,不知道細心的你發現問題了沒有,直觀上來說如果不細看可能會覺得很有道理,但錯就錯在的這種情況是不能考慮的,而且F[i]所代表的含義更加確切的說應該是,以第i個字符作爲結尾元素的最長遞增(後面的元素必須大於前面的元素,不能是等於)子序列的長度。而且此時,爲了避免第i個字母之前的字母都的情況,這裏還要對最終的結果和1取最大值。
對於此例子只需要一個反例【這裏舉的是最長遞減子序列的例子】:(注意標紅的部分爲錯誤的值,標綠的部分爲改正之後的值)。
那麼相應的正確的遞推公式應該爲:
習題:
攔截導彈(九度教程第 95 題)
合唱隊形(九度教程第 97 題)(需要從兩個方向運用兩次LIS)
3.最長公共子序列(LCS)
該博客有詳細解答,這裏就不展開了。
LCS的遞推方程如下所示:
其中c[i,j]表示字符串A[1,…,i]和字符串B[1,…,j]的最長公共子序列長度。
4.狀態與狀態轉移方程
5.動態規劃問題分析舉例
6.揹包問題
0-1揹包、完全揹包(剛還裝滿)、多重揹包(0-n揹包問題)