0 1揹包問題 回溯法

2021-07-13 16:50:30 字數 1625 閱讀 3956

0-1揹包問題 回溯法

一、專案描述

每種物品只有2 種選擇,分別為:裝入揹包或不裝入揹包,物品數和揹包容量已給定,計算裝入揹包物品的最大價值和最優裝入方案,用回溯法搜尋子集樹的演算法進行求解。

二、演算法設計

a. 物品有n種,揹包容量為c,分別用p[i]和w[i]儲存第i種物品的價值和重量,用x[i]標記第i種物品是否裝入揹包,用bestx[i]儲存第i種物品的最優裝載方案;

b. 用遞迴函式backtrack (i,cp,cw)來實現回溯法搜尋子集樹(形式引數i表示遞迴深度,n用來控制遞迴深度,形式引數cp和cw表示當前總價值和總重量,bestp表示當前最優總價值):

① 若i >n,則演算法搜尋到乙個葉結點,判斷當前總價值是否最優:

1> 若cp>bestp,更新當前最優總價值為當前總價值(即bestp=cp),更新裝載方案(即bestx[i]=xi);

② 採用for迴圈對物品i裝與不裝兩種情況進行討論(0≤j≤1):

1> x[i]=j;

2> 若總重量不大於揹包容量(即cw+x[i]*w[i]<=c),則更新當前總價 br=」「> 值和總重量(即cw+=w[i]*x[i],cp+=p[i]*x[i]), 對物品i+1呼叫遞迴函

數backtrack(i+1,cp,cw) 繼續進行裝載;

3> 函式backtrack(i+1,cp,cw)呼叫結束後則返回當前總價值和總重量

(即 cw-=w[i]*x[i],cp-=p[i]*x[i]);

4> 當j>1時,for迴圈結束;

③ 當i=1時,若已測試完所有裝載方案,外層呼叫就全部結束;

c. 主函式呼叫一次backtrack(1,0,0)即可完成整個回溯搜尋過程,最終得到的bestp和bestx[i]即為所求最大總價值和最優裝載方案。

三、程式

方法1

#include

int n,c,bestp;//物品的個數,揹包的容量,最大價值

int p[10000],w[10000],x[10000],bestx[10000];//物品的價值,物品的重量,x[i]暫存物品的選中情況,物品的選中情況

void backtrack(int i,int cp,int cw)

}else

for(j=0;j<=1; j++)

}}int main()

四、複雜度分析

深度優先搜尋的策略,

演算法從backtrack(1,0,0) 開始,呼叫void backtrack(int i,int cp,int cw)函式,

當n = 1時,直接就根據物品重量與揹包重量比較,只執行一步o(n)=o(1);

當n > 1時,進入for迴圈

for(j=0;j<=1; ++j)  // 列舉i所有可能的路徑,
在滿足限界函式和約束條件if(cw+x[i]*w[i]<=c)下,連續排列,直到碰壁,然後進行下一條路(另乙個條件),進行下一次的遍歷,直到結束,如圖

(最壞情況下有o(2n)個右兒子結點用限界函式,故計算0-1揹包問題的回溯演算法的時間複雜度為o(n2的n次方),在搜尋過程中的任何時刻,僅保留從開始結點到當前可擴充套件結點的路徑,其空間需求為o(從開始結點起最長路徑的長度)。所以,空間複雜度為o(n)

回溯法 0 1揹包問題

0 1揹包問題 給定n種物品和一揹包.物品i的重量是wi,其價值為ui,揹包的容量為c.問如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大?分析 0 1揹包是子集合選取問題,一般情況下0 1揹包是個np問題.第一步 確定解空間 裝入哪幾種物品 第二步 確定易於搜尋的解空間結構 可以用陣列p,w...

回溯法 0 1揹包問題

include include using namespace std class knap void knap backtrack int i 對第i個物品進行操作 return 如果沒有到葉子節點,就要對這個節點進行操作,即搜尋它的子樹,進入做左子樹表示可以選第i個,進入右子樹表示不能選第i個 ...

回溯法 0 1揹包問題

時限 1000ms記憶體限制 10000k總時限 3000ms 描述 需對容量為c 的揹包進行裝載。從n 個物品中選取裝入揹包的物品,每件物品i 的重量為wi 價值為pi 對於可行的揹包裝載,揹包中物品的總重量不能超過揹包的容量,最佳裝載是指所裝入的物品價值最高。輸入 多個測例,每個測例的輸入佔三行...