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 元。於是,他把每...