完全揹包問題 詳細解答

2021-10-22 21:28:05 字數 3209 閱讀 9031

首先完全揹包問題需要01揹包問題做鋪墊,如果讀者01揹包問題沒有解決,一定要理解之後,在看完全揹包問題,包括01揹包的優化!

這裡是01揹包

這裡是01揹包的全部優化

好,我們開始完全揹包!

有n種物品和乙個容量為v的揹包,每種物品都有無限件可用。第i種物品的體積是v[i],價值是val[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。

從定義中可以看出,與01揹包的區別01揹包最多只能拿一件物品,完全揹包則不然,只要空間夠多,一種物品我可以拿n件!

01揹包的狀態轉移方程為:dp(i,j)=max(dp(i-1,j),dp(i-1,j-v[i])+val[i])

完全揹包的狀態轉移方程:dp(i,j)=max(dp(i-1,j),dp(i,j-v)+val[i])

我們可以看出,完全揹包的動態轉移方程max中第二項為i,而不是i-1。

為什麼呢?

我們用01揹包的思想去推導,完全揹包的動態轉移方程

首先完全揹包問題的動態轉移方程可寫為

(w為val[i]簡寫)(v=v[i]簡寫)

dp(i,j)=max(dp(i-1,j) , dp(i-1,j-v)+w , dp(i-1,j-2v)+2w , dp(i-1,j-3v)+3w,

~~(以此類推到k) ,dp(i-1,j-k*v+kw))

我簡單解釋一下上面的方程,其實就是利用01揹包思想,要求無限個物品,實際上我最多能裝v/v[i]個 (總體積除以的單個個體積),所以我從裝0個,到裝乙個,2個,3個,k個這裡面一定有其中乙個,是能產生最大的價值!

然後我們利用上述公式推導出"完全揹包的狀態轉移方程"

開始推導

(時刻注意與這個方程的聯絡)

dp(i,j)=max(dp(i-1,j) , dp(i-1,j-v)+w , dp(i-1,j-2v)+2w , dp(i-1,j-3v)+3w,

~~(以此類推到k) ,dp(i-1,j-k*v+kw))

推導開始

還是利用01揹包思想

dp(i,j-v)=max( dp(i-1,j-v) , dp(i-1,j-2v)+w,dp(i-1,j-3v)+2w , dp(i-1,j-4v)+3w,~~

~依次類推到k , dp(i-1,j-kv)+(k-1)w) )

我們在這個方程兩側同時加上w,即可得到

dp(i,j-v)+w=max( dp(i-1,j-v)+w , dp(i-1,j-2v)+2w,dp(i-1,j-3v)+3w , dp(i-1,j-4v)+4w,~~dp(i-1,j-kv)+kw)

我們在回顧一下這個方程

dp(i,j)=max(dp(i-1,j) , dp(i-1,j-v)+w , dp(i-1,j-2v)+2w , dp(i-1,j-3v)+3w,

~~(以此類推到k) dp(i-1,j-k*v)+kw))

可以發現dp(i,j-v)+w可以替代

dp(i-1,j-v)+w , dp(i-1,j-2v)+2w , dp(i-1,j-3v)+3w,~~, dp(i-1,j-k*v)+kw

所以我們得出

完全揹包的狀態轉移方程:dp(i,j)=max(dp(i-1,j),dp(i,j-v)+w)

好了我們推導完成。

然後我們看下**:

#include

using

namespace std;

int n,v;

int v[

1010

],val[

1010];

int dp[

1010][

1010];

intmain()

for(

int i=

1; i<=n; i++

)for

(int j=

0; j<=v; j++)}

printf

("%d"

,dp[n]

[v])

;return0;

}

從巨集觀上理解,為什麼會這樣呢?

我從**的角度闡釋一下這個問題!

注意我們現在並沒有對dp陣列進行降維!

我們的j是從0開始的,依次遞增這個是完全揹包的關鍵,也是與01揹包本質的區別

dp[i][j]=max(dp[i-1][j],dp[i][j-v[i]]+val[i]);

首先要滿足完全揹包的動態轉移方程,就要先知道dp(i,j-v)的大小

正好我們是從0開始的,並不是從後往前,也就是當求到dp(i,j)時

dp(i,j-v),在前面已經求過!!!

所以我們可以應當理順的求出dp(i,j)而不再是向01揹包要考慮前i-1時候的狀態!

然後我們根據01揹包的優化原則對,完全揹包進行優化!

優化後的動態方程

dp[j]=max(dp[j],dp[j-v]+w)

**(裡面有乙個點需要理解,我寫在注釋裡了)

#include

using

namespace std;

int n,v;

int v[

1010

],val[

1010];

int dp[

1010];

intmain()

for(

int i=

1; i<=n; i++

)for

(int j=

0; j<=v; j++)}

printf

("%d"

,dp[v]);

//輸出最大體積,即最優解

return0;

}

感謝**,希望大家多多支援一鍵三連!!

嘻嘻~~

揹包問題(完全揹包)

1.矩陣鏈乘法 2.投資組合問題 3.完全揹包問題 4.01揹包問題 5.最長公共子串行 乙個揹包,可以放入n種物品,物品j的重量和價值分別為,如果揹包的最大重量限制是b,怎麼樣選擇放入揹包的物品以使得揹包的總價值最大?組合優化問題,設表示裝入揹包的第j個物品的數量,解可以表示為。那麼目標函式和約束...

完全揹包問題

這個是從ppt上弄過來的。完全揹包問題 有n種物品和乙個容量為v的揹包,每種物品都有無限件可用。放入第i種物品的耗費的空間是ci,得到的價值是wi。求解 將哪些物品裝入揹包,可使這些物品的耗費的空間總和不超過揹包容量,且價值總和最大 基本思路 這個問題非常類似於01揹包問題,所不同的是每種物品有無限...

完全揹包問題

設有n種物品,每種物品有乙個重量及乙個價值。但每種物品的數量是無限的,同時有乙個揹包,最大載重量為m,今從n種物品中選取若干件 用乙個物品可以多次選取 使其重量的和小於等於m,而價值的和為最大。輸入有多組資料,對於每組輸入資料第1行 兩個整數,m 揹包容量,m 200 和n 物品數量,n 30 第2...