資料結構與演算法——0-1揹包問題
第一種方法:
我們從第一個物品開始選擇,此時揹包的剩餘空間為weight;然後選擇第二個物品,此時有兩種情況,一是將該物品裝入揹包裡,二是不將該物品裝入揹包裡;
ret = max(package_0_1(num + 1, things, weight - things[num].first) + things[num].second, package_0_1(num + 1, things, weight));
。。。。直到將選擇完最後一個物品;這種方法的搜尋深度是n,每一層的搜尋都需要兩個分支,最壞就是需要O(2^n);
第二種方法:
第一種方法有一個重複判斷問題;遞迴呼叫函式的時候會重複執行相同的情況,所以我們採取一種方法來規避這種重複操作;
用一個二維陣列記錄遞迴函式執行的每一種情況,總共有n*m中情況,所以最多執行n*m次遞迴函式;時間複雜度變為O(n*m);
ret = max(package_0_1_advanced(num + 1, things, weight - things[num].first) + things[num].second, package_0_1_advanced(num + 1, things, weight));
第一種方法:
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>//pair, make_pair
using namespace std;
/*********************************************************************
引數num表示當前第num個物品
引數weight表示當前揹包剩下的容量
things中的成員的first表示物品的質量,second表示物品的價值
*********************************************************************/
int package_0_1(int num, vector<pair<int, int> > & things, int weight)
{
int ret;
if (num == things.size()){
ret = 0;
}
else if (weight < things[num].first){//當前揹包剩下的空間weight不能裝入第num個物品,所以繼續選擇下一個物品
ret = package_0_1(num + 1, things, weight);
}
else{//當前揹包剩下的空間weight可以裝入第num個物品,但是我們有兩個選擇可以裝入和不裝入,返回比較大的那個情況,返回的價值的大小
ret = max(package_0_1(num + 1, things, weight - things[num].first) + things[num].second, package_0_1(num + 1, things, weight));
//package_0_1(num + 1, things, weight - things[num].first) + things[num].second是選擇裝入第num個物品
}
return ret;
}
void input_data(int *number, vector<pair<int, int> > & things, int * total_weight)
{
cout << "Input the number of things: ";
cin >> *number;
cout << "Input the things' weight and value:\n";
int weight, value;
for (int i = 0; i < *number; ++i){
cin >> weight;
cin.get();
cin >> value;
cin.get();
things.push_back(make_pair(weight, value));
}
cout << "Input total weight: ";
cin >> *total_weight;
}
int main()
{
int total_weight;//揹包總的容量
int number;//物品的個數
vector<pair<int, int> > things;//pair<int, int> 表示物品的質量和價值的組合
input_data(&number, things, &total_weight);
/* //僅僅是為了測試輸入的資料對不對
cout << "Output the things: ";
for (int i = 0; i < things.size(); ++i){
cout << things[i].first << "," << things[i].second << " ";
}
cout << endl;
*/
int max_value = package_0_1(0, things, total_weight);//揹包可以裝入的物品的最大價值
cout << "max value is " << max_value << endl;
system("pause");
return 0;
}
第二種方法:
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>//pair, make_pair
using namespace std;
#define MAXNUMBER 100
#define MAXWEIGHT 10000
int book[MAXNUMBER][MAXWEIGHT];//記憶陣列
/*********************************************************************
引數num表示當前第num個物品
引數weight表示當前揹包剩下的容量
things中的成員的first表示物品的質量,second表示物品的價值
*********************************************************************/
int package_0_1_advanced(int num, vector<pair<int, int> > & things, int weight)
{
if (book[num][weight] >= 0){//如果此時判斷它的值大於等於0,則表示已經判斷過這種情況,直接返回;
return book[num][weight];
}
int ret;
if (num == things.size()){
ret = 0;
}
else if (weight < things[num].first){//當前揹包剩下的空間weight不能裝入第num個物品,所以繼續選擇下一個物品
ret = package_0_1_advanced(num + 1, things, weight);
}
else{//當前揹包剩下的空間weight可以裝入第num個物品,但是我們有兩個選擇可以裝入和不裝入,返回比較大的那個情況,返回的價值的大小
ret = max(package_0_1_advanced(num + 1, things, weight - things[num].first) + things[num].second, package_0_1_advanced(num + 1, things, weight));
//package_0_1(num + 1, things, weight - things[num].first) + things[num].second是選擇裝入第num個物品
}
book[num][weight] = ret;
return ret;
}
void input_data(int *number, vector<pair<int, int> > & things, int * total_weight)
{
cout << "Input the number of things: ";
cin >> *number;
cout << "Input the things' weight and value:\n";
int weight, value;
for (int i = 0; i < *number; ++i){
cin >> weight;
cin.get();
cin >> value;
cin.get();
things.push_back(make_pair(weight, value));
}
cout << "Input total weight: ";
cin >> *total_weight;
//初始化標誌陣列book, 比如book[i][j]的值記錄的是第i個商品,揹包剩下容量j的時候揹包包含的價值;
//如果此時判斷它的值大於等於0,則表示已經判斷過這種情況,直接返回;
//如果此時判斷它的值還是小於0,則表示還沒有判斷過這種情況;
memset(book, -1, sizeof(book));//將該陣列的初值置為-1
}
int main()
{
int total_weight;//揹包總的容量
int number;//物品的個數
vector<pair<int, int> > things;//pair<int, int> 表示物品的質量和價值的組合
input_data(&number, things, &total_weight);
/* //僅僅是為了測試輸入的資料對不對
cout << "Output the things: ";
for (int i = 0; i < things.size(); ++i){
cout << things[i].first << "," << things[i].second << " ";
}
cout << endl;
*/
int max_value = package_0_1_advanced(0, things, total_weight);//揹包可以裝入的物品的最大價值
cout << "max value is " << max_value << endl;
system("pause");
return 0;
}
比較好的參考連結:
http://www.cnblogs.com/daoluanxiaozi/archive/2012/05/06/2486105.html
http://shmilyaw-hotmail-com.iteye.com/blog/2009761
相關文章
- 【資料結構與演算法】揹包問題總結梳理資料結構演算法
- 【演算法】0-1揹包問題演算法
- 資料結構和演算法面試題系列—揹包問題總結資料結構演算法面試題
- 演算法——貪心演算法解0-1揹包問題演算法
- leetcode題解(0-1揹包問題)LeetCode
- 0-1揹包問題(動態規劃)動態規劃
- 揹包問題(01揹包與完全揹包)
- 動態規劃解0-1揹包問題動態規劃
- 0-1揹包問題 動態規劃法動態規劃
- 【演算法資料結構Java實現】Java實現動態規劃(揹包問題)演算法資料結構Java動態規劃
- 動態規劃之 0-1 揹包問題詳解動態規劃
- 揹包問題的演算法演算法
- 揹包問題例題總結
- 【動態規劃】0-1揹包問題原理和實現動態規劃
- [資料結構與演算法]-動態規劃之揹包演算法終極版資料結構演算法動態規劃
- 揹包問題解題方法總結
- 揹包問題
- 動態規劃0-1揹包動態規劃
- 0-1 揹包問題詳解(暫告一段落)
- 揹包問題的遞迴與非遞迴演算法遞迴演算法
- ACM 揹包問題ACM
- 01揹包問題
- acm演算法之三大揹包問題ACM演算法
- 揹包題型總結
- 揹包問題大合集
- 從【零錢兌換】問題看01揹包和完全揹包問題
- 資料結構與演算法之硬幣組合問題資料結構演算法
- 資料結構與演算法——迭代開啟url問題(連結串列)資料結構演算法
- 位元組面試演算法題-0,1揹包問題面試演算法
- 資料結構與演算法常見問題(面試題)不定時更新資料結構演算法面試題
- JavaScript中揹包問題(面試題)JavaScript面試題
- 資料結構與演算法入門題資料結構演算法
- JavaScript 揹包問題詳解JavaScript
- 資料結構與演算法-資料結構(棧)資料結構演算法
- 01揹包問題理解動態規劃演算法動態規劃演算法
- 用Python解決資料結構與演算法問題(三):線性資料結構之棧Python資料結構演算法
- 基礎面試題 — 資料結構與演算法面試題資料結構演算法
- 資料結構與演算法面試題80道資料結構演算法面試題