題目
給定n個重量為w1w1,w2w2,w3w3,…,wnwn,價值為v1v1,v2v2,v3v3,…,vnvn的物品和容量為cc的揹包,求這個物品中乙個最有價值的子集,使得在滿足揹包的容量的前提下,包內的總價值最大。
分析這個題目可以使用回溯法,回溯法即是當我們得到乙個序列時回到上一步的狀態,比如有n個物品,我們可以抽象成一棵滿二叉樹,向左表示將物品裝入包中,向右表示不裝入包中,當n為3時我們可以得到乙個這樣的滿二叉樹。
可以看到我們構建了乙個滿二叉樹只要便利這個二叉樹找到符合條件的就可以了。
**#include
#include
int n=8; //最大的物品個數
int v=110;
int max=0;
int v=;
int w=;
int sumv=0; //總價值
int sumw=0; //總體積
int digui(int m)
{if(sumw+w[m]>v || m>=n)
{if(max**分析
我們使用了遞迴的方法,判斷是否越界和是否超過最大的體積,然我們看一下這段**。
可以看出我們首先sumw+=w[m];sumv+=v[m]; digui(m+1);這三句表示將第m+1個物品放入包中,然後遞迴下乙個物品看是否符合條件,sumw-=w[m];sumv-=v[m];sumw+=w[m];
sumv+=v[m];
digui(m+1);
sumw-=w[m];
sumv-=v[m];
digui(m+1);
digui(m+1);這三句便是表示回溯的,這個digui(m+1)表示沒有將第m+1個物品放入包中(注意這裡的m+i個物品並不是digui(m+1)裡面的m+1,而是我們的下標是從0開始的。)。
eg:我們可以舉乙個例子來進行詳細說明一下。
如果現在有四個物品a,b,c,d.執行 sumw+=w[m]; sumv+=v[m];digui(m+1);後便會將abc三個物品都放入包中(假設將d放入其中的話包的空間不夠),然後便會執行sumw-=w[m];sumv-=v[m];digui(m+1);,前兩句表示將下標為m的物品從包中取出,因此此時這個物品是沒有裝入包的,然後執行digui(m+1);,表示遞迴,乙個迴圈的操作。。。。
回溯法 0 1揹包問題
0 1揹包問題 給定n種物品和一揹包.物品i的重量是wi,其價值為ui,揹包的容量為c.問如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大?分析 0 1揹包是子集合選取問題,一般情況下0 1揹包是個np問題.第一步 確定解空間 裝入哪幾種物品 第二步 確定易於搜尋的解空間結構 可以用陣列p,w...
0 1揹包問題 回溯法
0 1揹包問題 回溯法 一 專案描述 每種物品只有2 種選擇,分別為 裝入揹包或不裝入揹包,物品數和揹包容量已給定,計算裝入揹包物品的最大價值和最優裝入方案,用回溯法搜尋子集樹的演算法進行求解。二 演算法設計 a.物品有n種,揹包容量為c,分別用p i 和w i 儲存第i種物品的價值和重量,用x i...
回溯法 0 1揹包問題
include include using namespace std class knap void knap backtrack int i 對第i個物品進行操作 return 如果沒有到葉子節點,就要對這個節點進行操作,即搜尋它的子樹,進入做左子樹表示可以選第i個,進入右子樹表示不能選第i個 ...