01背包、完全背包、多重背包
生活随笔
收集整理的這篇文章主要介紹了
01背包、完全背包、多重背包
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
參考(都有些錯誤):
https://github.com/guanjunjian/Interview-Summary/blob/master/notes/algorithms/%E7%BB%8F%E5%85%B8%E7%AE%97%E6%B3%95/01%E8%83%8C%E5%8C%85.md
https://blog.csdn.net/na_beginning/article/details/62884939
https://github.com/guanjunjian/Interview-Summary/blob/master/notes/algorithms/%E7%BB%8F%E5%85%B8%E7%AE%97%E6%B3%95/01%E8%83%8C%E5%8C%85.md
https://blog.csdn.net/na_beginning/article/details/62884939
?
#include <iostream> #include <sstream> #include <vector> #include <string>using namespace std;/* 01背包問題 每個物品僅一個 狀態轉移公式:F[i][j] = F[i - 1][j] 和 F[i - 1][j - W[i]] + V[i] 大的那個值 C背包總重量 W每個物品重量 V每個物品價值 n物品總數 inp具有最大價值時,標記哪個物品在包中 返回最大價值 */ int packages(int C, vector<int> &W, vector<int> &V, int n, vector<int> &inp) {vector<vector<int> > F(n, vector<int>(C + 1));//F[i][j]記錄背包可用重量為j時,前i個物品的最大價值for (int i = 0; i < n; i++)//初始化表格 {for (int j = 0; j < F[0].size(); j++)F[i][j] = 0;}for (int j = 1; j < F[0].size(); j++)//初始化第一行F[0][j] = (j < W[0]) ? 0 : V[0];//可用重量j大于物品重量,則裝入該物品,加上該物品價值for (int i = 1; i < n; i++){for (int j = 1; j < F[0].size(); j++){if (j < W[i])F[i][j] = F[i - 1][j];//裝不下該物品elseF[i][j] = (F[i - 1][j] < F[i - 1][j - W[i]] + V[i]) ? F[i - 1][j - W[i]] + V[i] : F[i - 1][j];//可裝下該物品。狀態轉移方程 }}int result = F[n - 1][F[0].size() - 1];//最大價值//inp標記哪些物品在包中int j = C;for (int i = n-1; i >0 ; i--)//i不可為0,否則F[i-1]越界 {if (j>W[i] && F[i][j] == F[i - 1][j - W[i]] + V[i])//注意需要j>W[i] {inp[i] = 1;j -= W[i];}}if (F[0][j] > 0)//如果背包還可裝下,則包含第一個物品inp[0] = 1;//輸出動態規劃數組for (int i = 0; i < n; i++){for (int j = 0; j < F[0].size(); j++)cout << F[i][j] << " ";cout << endl;}return result; }/* 01背包問題 滾動數組優化動態規劃的空間 原空間OnC,先空間O2C,但是無法輸出有哪些物品在包中 */ int packages_good(int C, vector<int> &W, vector<int> &V, int n) {vector<vector<int> > F(2, vector<int>(C + 1));//F[i][j]記錄背包可用重量為j時,前i個物品的最大價值for (int i = 0; i < 2; i++)//初始化表格 {for (int j = 0; j < F[0].size(); j++)F[i][j] = 0;}for (int j = 1; j < F[0].size(); j++)//初始化第一行F[0][j] = (j < W[0]) ? 0 : V[0];//可用重量j大于物品重量,則裝入該物品,加上該物品價值int k = 0;for (int i = 1; i < n; i++){k = i & 1;//滾動for (int j = 1; j < F[0].size(); j++){if (j < W[i])F[k][j] = F[k ^ 1][j];//裝不下該物品elseF[k][j] = (F[k ^ 1][j] < F[k ^ 1][j - W[i]] + V[i]) ? F[k ^ 1][j - W[i]] + V[i] : F[k ^ 1][j];//可裝下該物品 }}return F[k][F[0].size() - 1];//最大價值 }/* 完全背包 每個物品不限制數量 狀態轉移公式:F[i][j] = F[i - 1][j] 和 F[i][j - W[i]] + V[i] 大的那個值,標記哪些物品在包中也改變 注意是F[i][j - W[i]] + V[i] 也可優化空間 */ int packages_full(int C, vector<int> &W, vector<int> &V, int n, vector<int> &inp) {vector<vector<int> > F(n, vector<int>(C + 1));//F[i][j]記錄背包可用重量為j時,前i個物品的最大價值for (int i = 0; i < n; i++)//初始化表格 {for (int j = 0; j < F[0].size(); j++)F[i][j] = 0;}for (int j = 1; j < F[0].size(); j++)//初始化第一行F[0][j] = (j < W[0]) ? 0 : ((j/W[0])*V[0]);//每個物品不止一個for (int i = 1; i < n; i++){for (int j = 1; j < F[0].size(); j++){if (j < W[i])F[i][j] = F[i - 1][j];//裝不下該物品elseF[i][j] = (F[i - 1][j] < F[i][j - W[i]] + V[i]) ? F[i][j - W[i]] + V[i] : F[i - 1][j];//可裝下該物品。狀態轉移方程 }}int result = F[n - 1][F[0].size() - 1];//最大價值//inp標記哪些物品在包中int j = C;int i = n - 1;while (i){while(j && j > W[i] && F[i][j] == F[i][j - W[i]] + V[i]) //如果包含該物品,則一直循環看包含幾個該物品 {inp[i]++;j -= W[i];}i--;//不包含該物品,則跳到下一個物品 }//輸出動態規劃數組for (int i = 0; i < n; i++){for (int j = 0; j < F[0].size(); j++)cout << F[i][j] << " ";cout << endl;}return result; }/* 多重背包 每個物品有數量限制 */ int packages_multi(int C, vector<int> &W, vector<int> &V, int n, vector<int> &inp, vector<int> &N)//N會被修改 {vector<vector<int> > F(n, vector<int>(C + 1));//F[i][j]記錄背包可用重量為j時,前i個物品的最大價值for (int i = 0; i < n; i++)//初始化表格 {for (int j = 0; j < F[0].size(); j++)F[i][j] = 0;}for (int j = 1; j < F[0].size(); j++)//初始化第一行,每個物品有對應數量N限制 {int count = (N[0] > j / W[0]) ? j / W[0] : N[0];//可用空間為j時,可以放多少個當前物品,min{可放入數量,物品數量}F[0][j] = (j < W[0]) ? 0 : (count*V[0]);}for (int i = 1; i < n; i++){for (int j = 1; j < F[0].size(); j++){if (j < W[i])F[i][j] = F[i - 1][j];//裝不下該物品else{int count = (N[i] > j / W[i]) ? j / W[i] : N[i];F[i][j] = F[i - 1][j];//不放當前物品for (int k = 1; k <= count; k++)//看放入多少個當前物品可以讓F[i][j]最大 {int tmp = F[i - 1][j - k * W[i]] + k * V[i];//放入k個當前物品if (tmp > F[i][j])F[i][j] = tmp;}}}}int result = F[n - 1][F[0].size() - 1];//最大價值cout << result << endl;//inp標記哪些物品在包中int j = C;int i = n - 1;while (i){while (j && N[i] && j > W[i] && F[i][j] == F[i][j - W[i]] + V[i]) //如果包含該物品,則一直循環看包含幾個該物品 {inp[i]++;j -= W[i];--N[i];}i--;//不包含該物品,則跳到下一個物品 }//輸出動態規劃數組for (int i = 0; i < n; i++){for (int j = 0; j < F[0].size(); j++)cout << F[i][j] << " ";cout << endl;}return result; }int main() {vector<int> W{ 4,5,6,2,2 };vector<int> V{ 6,4,5,3,6 };int C = 9;int n = W.size();vector<int> inp(n, 0);//標記是否在包中cout << "1、01背包最大總價值:" << packages(C, W, V, n, inp) << endl;cout << "在背包中的物品編號: ";for (int i = 0; i < inp.size(); i++){if (inp[i] == 1)cout << i << " ";}cout << endl;cout << "2、01背包滾動數組優化最大總價值,無法輸出有哪些物品在背包中:" << packages_good(C, W, V, n) << endl;cout << endl;vector<int> inp1(n, 0);//標記是否在包中cout << "3、完全背包最大總價值:" << packages_full(C, W, V, n, inp1) << endl;cout << "輸出在背包中物品: ";for (int i = 0; i < inp1.size(); i++){cout << inp1[i] << " ";}cout << endl;cout << endl;vector<int> N{ 1,2,2,2,4 };//每個物品數量vector<int> inp2(n, 0);//標記是否在包中cout << "4、多重背包最大總價值:" << packages_multi(C, W, V, n, inp2, N) << endl;cout << "輸出在背包中物品: ";for (int i = 0; i < inp2.size(); i++){cout << inp2[i] << " ";}cout << endl;return 0; }?
轉載于:https://www.cnblogs.com/beixiaobei/p/10914211.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的01背包、完全背包、多重背包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: stata15中文乱码_Stata转ex
- 下一篇: 没有基础学python_python没有