014 揹包問題 動態規劃

2022-03-22 17:41:58 字數 2618 閱讀 7542

01揹包是在m件物品取出若干件放在空間為w的揹包裡,每件物品的體積為w1,w2……wn,與之相對應的價值為p1,p2……pn。求能獲得的最大總價值。

v[i,j]表示從前i件物品中取出的,能裝入體積為j的揹包的物品的最大總價值。

初始化條件:

v[i,0]和v[0,j]都為0,我們從其意義上就可以理解。

狀態轉移方程:

v[i,j]=max ,前後分別為第i件物品不取和取得情況。

總的就是下面的遞推式:

表的大小為n*c,所以演算法的時間複雜度為θ(nc),經過一些修改空間複雜度可以控制在θ(c)內。

1.θ(nc)的空間。

for(int i=0;i<=v;i++) dp[0][i]=0; // 初始條件

for(int i=1;i<=n;i++)

for(int v=c[i];v<=v;v++)

}cout<2.在空間上做一些優化,θ(c)的空間。for(int i=0;i<=v;i++) dp[i]=0; // 初始條件

for(int i=1;i<=n;i++)

}cout我們知道原來**中的二維陣列的i是為了表示在前i個物品中做選擇,同時也標誌第i個物品是否已經選取了。

每次決策的時候是決定第i個物品是否要選取。比如,對dp[i-1][v-ci]我們知道第i個物品並沒有選取,而對於dp[i][v-ci]我們可以知道第i個物品已經被選取了,我們每次自從前面乙個狀態(i-1)來決策第i個是否要選。

而空間優化的**通過另外一套機制來保證乙個物品只選一次。

我們可以看到第二個**中的v是按逆序迴圈的,這樣做是很有必要的:

這是因為要保證第i次迴圈中的狀態dp[v]是由狀態dp[v-c]遞推而來。換句話說,這正是為了保證每件物品只選一次,保證在考慮「選入第i件物品」這件策略時,依據的是乙個沒有已經選入第i件物品的子結果dp[v-ci](如果已經選入了,即dp[v]已經完成狀態轉移方程,不會再進行)。

有n件物品和乙個容量為v的揹包。放入第i件物品所耗的容量為ci,得到的價值為wi,但是同一件物品可以放入任意多件,問您最多可以獲得多少價值。

這裡與01揹包不同的是每一件物品可以選任意多件,我們只需要在狀態轉移方程上進行一些改動:

v[i][j]=max

這裡的k表示的是第i件物品選取的數量,在程式中,我們只需為k多進行乙個迴圈,並注意k的取值範圍,就可以解決完全揹包問題。

f[0] ←

f[0] ←

for i←1 to n

do for j←1 to v

do for k←0 to j/c[i]

if(j >= k*c[i])

then f[i][k] ← max(f[i][k],f[i-1][j-k*c[i]]+k*w[i])

return f[n][v]

直接放**:

for(int i=0;i<=v;i++) dp[i]=0; // 初始條件

for(int i=1;i<=n;i++)

}這裡和01揹包的空間優化**差不多,改變的是v的迴圈順序。前面v逆序迴圈的目的是為了保證每件物品只選擇一次,改為正序迴圈後,每件物品選擇的次數可以是任意的。

看下面這個例子dp[v-ci]後選擇了第i件物品變為dp[v],而dp[(v+ci)-ci]仍然可以選擇第i件物品,變為dp[v+ci]。

有n件物品和乙個容量為v的揹包。放入第i件物品所耗的容量為ci,得到的價值為wi,但是第i件物品最多可以放入mi件,問您最多可以獲得多少價值。

(1)二維陣列的做法

與前面兩種揹包的做法類似,只在狀態轉移方程上做一些更改。

dp[i][v]=max

就不貼**了。

(2)轉化為01揹包

空間優化的做法是將其轉化為01揹包,並採用二進位制的做法進行拆分,即拆分成1件、2件、4件...。

for(int i=1;i=0;k*=2)

num-=mul; // 分完那堆之後從總數上扣掉 }}

#include

using namespace std;

const int n = 3;//物品個數

const int v = 8;//揹包容量

int weight[n + 1] = ;

int value[n + 1] = ;

int num[n + 1] = ;

int f[v + 1] = ;

/*f[v]:表示把前i件物品放入容量為v的揹包中獲得的最大收益。

f[v] = max(f[v],f[v - weight[i]] + value[i]);

v的為逆序

*/void zeroonepack(int nweight,int nvalue)}

/*f[v]:表示把前i件物品放入容量為v的揹包中獲得的最大收益。

f[v] = max(f[v],f[v - weight[i]] + value[i]);

v的為增序

*/void completepack(int nweight,int nvalue)}

int multiknapsack()

else

zeroonepack(ncount * weight[i],ncount * value[i]);}}

return f[v];}

int main()

{cout<

動態規劃 揹包問題

給定n個物品,重量是,價值是,包的容量 承重 是w 問,放入哪些物品能使得包內價值最大 1 需要將問題轉化為子問題,通過遞迴實現,且子問題必然與父問題存在關聯 2 定義v i,j 表示為,當item取自前i個items且揹包capacity j 時,揹包問題的最優解,也即最高的價值。3 從前i個it...

動態規劃 揹包問題

不廢話,直接上 動態規劃,揹包問題。輸入為 int n 物品的種類數。int n weight 各件物品的重量。int n value 各種物品的價值。int w 揹包最大的裝載重量。輸出 v n b 的值,最大的裝載價值。x n 各類物品的裝載數量。author huangyongye publi...

動態規劃 揹包問題

1 開心的金明 問題描述 金明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間他自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說 你的房間需要購買哪些物品,怎麼布置,你說了算,只要不超過n 元錢就行 今天一早金明就開始做預算,但是他想買的東西太多了,肯定會超過媽媽限定的n 元。於是,他把每...