一: 思想
首先要了解」動態規劃「,必須先知道什麼叫做」多階段決策「,百科裡面對這個問題解釋的很全,我就load一段出來,
大家得要好好品味,好好分析。
上面圖中最後一句話就定義了動態規劃是要幹什麼的問題。
二:使用規則
現在我們知道動態規劃要解決啥問題了,那麼什麼情況下我們該使用動態規劃呢?
① 最優化原理(最優子結構性質):
如果乙個問題的最優策略它的子問題的策略也是最優的,則稱該問題具有「最優子結構性質」。
② 無後效性:
當乙個問題被劃分為多個決策階段,那麼前乙個階段的策略不會受到後乙個階段所做出策略的影響。
③ 子問題的重疊性:
這個性質揭露了動態規劃的本質,解決冗餘問題,重複的子問題我們可以記錄下來供後階段決策時
直接使用,從而降低演算法複雜度。
三:求解步驟
① 描述最優解模型。
② 遞迴的定義最優解,也就是構造動態規劃方程。
③ 自底向上的計算最優解。
④ 最後根據計算的最優值得出問題的最佳策略。
四:與其他演算法的差異
① 遞迴: 遞迴採用的是「由上而下」的解題策略並帶有可能的」子問題「重複呼叫,時間複雜度自然高。
而」動態規劃「採用」自下而上「並帶有臨時儲存器儲存上一策略的最優解,空間換時間。
② 分治: 同樣兩者都是將問題劃分為很多的子問題,不同的是」動態規劃「中各子問題是相互聯絡的。
③ 貪心: 要注意的是貪心演算法每走一步都是不可撤回的,而動態規劃是在乙個問題的多種策略中尋找
最優策略,所以動態規劃中前一種策略可能會被後一種策略推翻。
揹包問題
01揹包: 有n件物品和乙個重量為m的揹包。(每種物品均只有一件)第i件物品的重量是w[i],價值是p[i]。求解將哪些物品裝入揹包可使價值總和最大。
完全揹包: 有n種物品和乙個重量為m的揹包,每種物品都有無限件可用。第i種物品的重量是w[i],價值是p[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包重量,且價值總和最大。
多重揹包: 有n種物品和乙個重量為m的揹包。第i種物品最多有n[i]件可用,每件重量是w[i],價值是p[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包重量,且價值總和最大。
先來分析01揹包:
01揹包(zeroonepack): 有n件物品和乙個容量為v的揹包,每種物品均只有一件。第i件物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可使價值總和最大。
這是最基礎的揹包問題,特點是:每種物品僅有一件,可以選擇放或不放。
用子問題定義狀態:即f[i][v]表示前i件物品恰放入乙個容量為v的揹包可以獲得的最大價值。則其狀態轉移方程便是:
f[i][v]=max
把這個過程理解下:
在前i件物品放進容量v的揹包時,它有兩種情況
情況一: 第i件不放進去,這時所得價值為:f[i-1][v]
情況二: 第i件放進去,這時所得價值為:f[i-1][v-c[i]]+w[i]
(第二種是什麼意思?就是如果第i件放進去,那麼在容量v-c[i]裡就要放進前i-1件物品)
最後比較第一種與第二種所得價值的大小,哪種相對大,f[i][v]的值就是哪種。 (這裡是重點,理解!)
這裡可以將2維陣列降為1維陣列,用f[0...v]表示,f[v]表示把前i件物品放入容量為v的揹包裡得到的價值。
把i從1-n迴圈後,最後f[v]表示所求最大值。
這裡的f[v]就相當於f[i][v],那麼,如何得到f[i-1][v]和f[i-1][v-c[i]]+w[i]?
首先要知道,我們是通過i從1-n的迴圈來表示前i件物品存入的狀態。即for i = 1...n
現在思考如何能在是f[v]表示當前狀態是容量為v的揹包所得價值,而又使f[v]和f[v-c[i]]+w[i]標籤前一狀態的價值?
逆序 這就是關鍵
for i=1..n
for v=v..0
f[v]=max;
測試資料: 10,3 3,4 4,5 5,6
i = 0是初始化,為了i = 1的時候遞推時使用,i = 1時因為物品1的大小為3,所以大於3時物品價值均為4。
i = 2時從10開始迴圈回來,只要有空間時就放入物品2,放不下時但是可以替換時就用物品2替換物品1,因為揹包空間大於物品2卻小於物品1+物品2時就取價值大的乙個。
i = 3時從10開始迴圈,代入狀態轉移方程可以得到最大值。
這裡以一道題目來具體看看:
題目:
題目大意:從給定各種價值和體積的物品中選取n件,裝進容積為v揹包。 問最多背
包中能裝多少價值的東西。
5 10(n<=1000 v<=1000)
1 2 3 4 5 (每一件對應的 價值 )value[1002]
5 4 3 2 1 (每一件的重量)weight[1002]
問最多揹包中能裝多少價值的東西。
14#include
#include
int value[50001],weight[50001],record[50001];
int main()
for(i=1;i<=n;i++)
memset(record,0,sizeof(record));
record[0]=0;for(i=1;i<=n;i++)
}}printf("%d\n",record[v]);
}return 0;
}
演算法之動態規劃
鋼條切割問題 鋼條切割問題出現在 演算法導論 一書第204頁,作為動態規劃的例題出現,該題內容如下 serling公司購買長鋼條,將其切割為短鋼條 切割工序本身沒有成本支出。公司管理層希望知道最佳的切割方案。假定我們知道serling公司 一段長為i英吋的鋼條的 為pi i 1,2,單位為美元 鋼條...
演算法實驗之動態規劃
設有n種不同面值的硬幣,各硬幣的面值存於陣列t 1 n 中。現要用這些面值的硬幣來找錢,可以實用的各種面值的硬幣個數不限。當只用硬幣面值t 1 t 2 t i 時,可找出錢數j的最少硬幣個數記為c i,j 若只用這些硬幣面值,找不出錢數j時,記c i,j 輸入結果儲存在1.txt中,輸出結果儲存在2...
動態規劃之LCS演算法
lcs是longest common subsequence的縮寫,即最長公共子串行。乙個序列,如果是兩個或多個已知序列的子串行,且是所有子串行中最長的,則為最長公共子串行。另外還有個分支問題 最長公共子串。子串的字元位置必須連續,而子串行則不必,從原序列中去掉任意的元素獲得的新序列。可以看出,子串...