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