演算法之動態規劃

2021-07-03 23:34:52 字數 2919 閱讀 1687

一: 思想

首先要了解」動態規劃「,必須先知道什麼叫做」多階段決策「,百科裡面對這個問題解釋的很全,我就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的縮寫,即最長公共子串行。乙個序列,如果是兩個或多個已知序列的子串行,且是所有子串行中最長的,則為最長公共子串行。另外還有個分支問題 最長公共子串。子串的字元位置必須連續,而子串行則不必,從原序列中去掉任意的元素獲得的新序列。可以看出,子串...