0 1揹包問題(回溯法)

2021-09-07 02:53:35 字數 1705 閱讀 5955

給定n種物品和乙個揹包容量為c的揹包,物品i的重量是wi,其價值為vi,利用回溯法來實現求解如何使裝入揹包中的物品的總價值最大。

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

(2)用遞迴函式knapsack(i,bv,bw)來實現回溯法搜尋子集樹(形式引數i表示遞迴深度,n用來控制遞迴深度,形式引數bv和bw表示當前總價值和總重量,bestv表示當前最優總價值);

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

(4)若bv>bestv,更新當前最優總價值為當前總價值,再更新裝載方案;

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

1)x[i]=j;

2)若總重量不大於揹包容量(即bw+x[i]*w[i]<=c),則更新當前總價值和總重量(即bw+=w[i]*x[i],bv+=v[i]*x[i]), 對物品                     i+1呼叫遞迴函式knapsack (i+1,cp,cw) 繼續進行裝載;

3)函式knapsack (i+1,bv,bw)呼叫結束後則返回當前總價值和總重量(即 bw-=w[i]*x[i],bv-=v[i]*x[i]);

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

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

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

#include#includeusing namespace std;

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

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

void knapsack(int i,int bv,int bw)

}else

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

}}int main()

printf("請依次輸入物品的重量:\n");

for(int i=1; i<=n; i++)

scanf("%d",&w[i]);

knapsack(1,0,0);

printf("最大價值為:\n");

printf("%d\n",bestv);

printf("被選中的物品依次是(0表示未選中,1表示選中)\n");

計算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揹包問題 回溯法

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個 ...