01揹包、完全揹包、多重揹包、分組揹包
參考連結:
各種揹包的描述:
01揹包(ZeroOnePack): 有N件物品和一個容量為V的揹包。(每種物品均只有一件)第i件物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可使價值總和最大。
完全揹包(CompletePack): 有N種物品和一個容量為V的揹包,每種物品都有無限件可用。第i種物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。
多重揹包(MultiplePack): 有N種物品和一個容量為V的揹包。第i種物品最多有n[i]件可用,每件費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。
分組揹包有N件物品和一個容量為V的揹包。第i件物品的費用是c[i],價值是w[i]。這些物品被劃分為若干組,每組中的物品互相沖突,最多選一件。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。
01揹包問題
容量為10的揹包,有5種物品,每種物品只有一個,其重量分別為5,4,3,2,1,其價值分別為1,2,3,4,5。
設計演算法,實現揹包內物品價值最大。
程式碼如下(輸出14)
#include <iostream> #include<algorithm> using namespace std; int main() { int total_weight = 10; int w[6] = { 0,5,4,3,2,1}; int v[6] = { 0,1,2,3,4,5}; int dp[11] = { 0 }; for (int i = 1; i <= 5; i++) for (int j = 10; j >= w[i]; j--) dp[j] = max(dp[j], dp[j - w[i]] + v[i]); cout << "總的價值為: " << dp[10] << endl; return 0; }
完全揹包問題
容量為10的揹包,有5種物品,每種物品數量無限,其重量分別為5,4,3,2,1,其價值分別為1,2,3,4,5。
設計演算法,實現揹包內物品價值最大。
程式碼如下(輸出50)
#include <iostream> #include<algorithm> using namespace std; int main() { int total_weight = 10; int w[6] = { 0,5,4,3,2,1}; int v[6] = { 0,1,2,3,4,5}; int dp[11] = { 0 }; for (int i = 1; i <= 5; i++) for (int j = w[i]; j <= 10;j++) dp[j] = max(dp[j],dp[j - w[i]] + v[i]); cout << "總的價值為: " << dp[10] << endl; return 0; }
多重揹包問題
容量為10的揹包,有5種物品,每種物品數量分別為1,2,1,2,1,其重量分別為5,4,3,2,1,其價值分別為1,2,3,4,5。
設計演算法,實現揹包內物品價值最大。
程式碼如下(輸出16)
#include <iostream>
#include<algorithm>
using namespace std;
int main()
{
int total_weight = 10;
int w[6] = { 0,5,4,3,2,1 };
int v[6] = { 0,1,2,3,4,5 };
int cot[6] = { 0,1,2,1,2,1 };
int dp[11] = { 0 };
for (int i = 1; i <= 5; i++)
for (int k = 1; k <= cot[i];k++)
for (int j = 10; j >= w[i]; j--)
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
cout << "總的價值為: " << dp[10] << endl;
return 0;
}
分組揹包問題
乍一看好像很難的樣子,其實仔細想想很簡單,這種問題完全可以用01揹包解決。 對於分組揹包,可以這樣想:雖然分成很多組,但只能選一個,或者不選,這和01揹包是一樣的,也就是說,對於01揹包裡每一個獨一無二的物品,對應的分組揹包就是每一組中選擇一個物品,這樣來看,完全就是01揹包問題。
下面是狀態方程:
for(int i = 1; i <= z; i++)
for(int j = V; j >= 1; j--)
for(int k = 1; k <= n; k++)
dp[j] = max(dp[j - w[i][k]] + p[i][k], dp[j]);
其中,z是分組數,V是揹包體積,n是每組物品數量,w和p分別是第i組第k個物品的體積和價值。
為什麼要這樣寫呢?可以想一下01揹包的狀態方程,和這個外兩層的迴圈是一樣的,不一樣的是裡面又加了一層,這層迴圈是遍歷每一組的物品用的,對於dp[]中每一個狀態都是迴圈了一遍每一組的物品才換到下一個的,所以對後面的沒有影響,也就保證了每組物品最多隻有一件。