問題:
有n件物品和乙個容量為v的揹包。第i件物品的費用是c[i],價值是w[i]。
求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。
分析:用dp[i][v]表示將前i個物品放入價值為v的揹包能獲得的最大價值
計算dp[i][v]時,分兩種情況:第i件物品選或者不選,二者中價值較大的值就是f[i][v]的值,
即:dp[i][v]=max
注意: 矩陣c和w的第一位要空出來,因為i == 0的情況被跳過,之後的演算法也是同理。
考慮減少空間的開銷,由於計算過程為從上到下,從左到右,dp[i][v]實際上只依賴於dp[i-1][0...v]這些值。如果使用從右到左的順序,就可以只使用一維陣列進行計算。vectorc = ; // 費用
vectorw = ; // 價值
int n = c.size()-1;
int v = 2;
vector> dp(n+1, vector(v+1));
for(int i = 0; i <= n; i++)
for(int v = 0; v <= v; v++)
cout << dp[n][v] << endl;
問題:vectordp2(n+1);
for(int i = 0; i <= n; i++)
for(int v = v; v >= 0; v--)
有n種物品和乙個容量為v的揹包,每種物品都有無限件可用。第i種物品的費用是c[i],價值是w[i]。
求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大
分析:用dp[i][v]表示將前i個物品放入價值為v的揹包能獲得的最大價值
計算dp[i][v]時,也是可以分為兩種情況:第i件物品選n件(n>=1)或者不選,
也即: dp[i][v] = max(dp[i-1][v], dp[i][v-c[i]]+w[i])
需要注意,當選定第i件物品時,標號還是為i,因為選定之後還可以繼續選i
同樣,完全揹包也可以進行減少空間開銷。相對於01揹包,只需要修改v遍歷的順序就可以了。原因是:在01揹包中,倒序的目的是保證決策是否選擇i時依據的是沒有選入i的子結果,而在完全揹包中,我們正需要選入i的子結果,所以他們的順序時相反的。vector> dp(n+1, vector(v+1));
for(int i = 0; i <= n; i++)
for(int v = 0; v <= v; v++)
問題:vectordp2(n+1);
for(int i = 0; i <= n; i++)
for(int v = 0; v <= v; v++)
有n種物品和乙個容量為v的揹包。第i種物品最多有n[i]件可用,每件費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。
分析:簡單地,可以將第i個物品分為n[i]個物品來考慮,然後使用01揹包的演算法解決問題。但是這樣會大量增加物品的數量,複雜度比較高。可以考慮將物品用二進位制進行劃分,分為:1, 2, 4, ...,
其中中隱含了對指數的判斷,簡化了過程。之後再對c,w進行01揹包的處理就行了。int main() ; // 費用
vectorw = ; // 價值
vectornum = ;
int n = c.size();
int v = 20;
vectorc,w;
c.push_back(0);
w.push_back(0); // 第乙個值置空
for(int i = 0; i < n; i++)
}n = c.size()-1;
vectordp(v+1);
for(int i = 0; i <= n; i++)
for(int v = v; v >= 0; v--)
cout << dp[v] << endl;
}
問題:有的物品只可以取一次,有的物品可以取無限次,有的物品可以取的次數有乙個上限。
分析:這個問題實際上也就是前三個問題的疊加,首先還是使用二進位制拆分的方式將只可以取有限次數的物品轉變為只可以取一次的物品(多重揹包問題),然後剩下的就是01揹包和完全揹包的混合,因為二者的實現只是在v的遍歷順序上有區別,只需要對物品i進行判斷,對01揹包進行逆序遍歷,完全揹包進行順序遍歷即可。
問題:vectordp(v+1);
for(int i = 0; i <= n; i++)
} else }}
二維費用的揹包問題是指:對於每件物品,具有兩種不同的費用;選擇這件物品必須同時付出這兩種代價;對於每種代價都有乙個可付出的最大值(揹包容量)。問怎樣選擇物品可以得到最大的價值。設這兩種代價分別為代價1和代價2,第i件物品所需的兩種代價分別為a[i]和b[i]。兩種代價可付出的最大值(兩種揹包容量)分別為v和u。物品的價值為w[i]。
分析:多了乙個條件,新增一維即可,同01揹包。
問題:int dp[n+1][v1+1][v2+1] = ;
for(int i = 0; i <= n; i++)
for(int v1 = 0; v1 <= v1; v1++)
for(int v2 = 0; v2 <= v2; v2++)
else
dp[i][v1][v2] = max(dp[i-1][v1][v2], dp[i-1][v1-c1[i]][v2-c2[i]]+w[i]);
}cout << dp[n][v1][v2] << endl;
有n件物品和乙個容量為v的揹包。第i件物品的費用是c[i],價值是w[i]。這些物品被劃分為若干組,每組中的物品互相衝突,最多選一件。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。
分析:可以這樣考慮,對於每個組,可以分為兩種情況:選這一組中的物品,不選這一組中的物品
即: dp[k][v]=max,}; // 費用
vector> w = ,}; // 價值
int n = c.size()-1;
int v = 5;
vector> dp1(n+1, vector(v+1,0));
for(int k = 0; k <= n; k++)
for(int v = 0; v <= v; v++) }}
cout << dp1[n][v] << endl;也可以使用一維陣列減少空間的開銷
vectordp(n+1, 0);
for(int k = 0; k <= n; k++)
for(int v = v; v >= 0; v--)
for(int i = 0; i < c[k].size(); i++)
cout << dp[v] << endl;
動態規劃 揹包問題
給定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 元。於是,他把每...