回溯法 01揹包問題

2021-08-15 23:46:05 字數 2256 閱讀 1843

【回溯法】--01揹包問題

1、問題描述

給定n種物品和一揹包。物品i的重量是wi>0,其價值為vi>0,揹包的容量為c。問應如何選擇裝入揹包中的物品,使得裝入揹包中物品的總價值最大? (要求使用回溯法)

例如:

2、演算法分析

【整體思路】

01揹包屬於找最優解問題,用回溯法需要構造解的子集樹。對於每乙個物品i,對於該物品只有選與不選2個決策,總共有n個物品,可以順序依次考慮每個物品,這樣就形成了一棵解空間樹: 基本思想就是遍歷這棵樹,以列舉所有情況,最後進行判斷,如果重量不超過揹包容量,且價值最大的話,該方案就是最後的答案。

在搜尋狀態空間樹時,只要左子節點是可乙個可行結點,搜尋就進入其左子樹。對於右子樹時,先計算上界函式,以判斷是否將其減去(剪枝)。

上界函式bound():當前價值cw+剩餘容量可容納的最大價值<=當前最優價值bestp。 

為了更好地計算和運用上界函式剪枝,選擇先將物品按照其單位重量價值從大到小排序,此後就按照順序考慮各個物品。

【舉例說明】

對於n=4的0/1揹包問題,其解空間樹如圖所示,樹中的16個葉子結點分別代表該問題的16個可能解。 

【演算法設計】

利用回溯法試設計乙個演算法求出0-1揹包問題的解,也就是求出乙個解向量xi (即對n個物品放或不放的一種的方案)

其中, (xi = 0 或1,xi = 0表示物體i不放入揹包,xi =1表示把物體i放入揹包)。

在遞迴函式backtrack中,

當i>n時,演算法搜尋至葉子結點,得到乙個新的物品裝包方案。此時演算法適時更新當前的最優價值

當i【時間複雜度&&優化】  

因為物品只有選與不選2個決策,而總共有n個物品,所以時間複雜度為

因為遞迴棧最多達到n層,而且儲存所有物品的資訊也只需要常數個一維陣列,所以最終的空間複雜度為o(n)。

相關鏈結1

相關鏈結2

相關鏈結3

【源**】        

#include #include //#include using namespace std;

int n;//物品數量

double c;//揹包容量

double v[100];//各個物品的價值 value

double w[100];//各個物品的重量 weight

double cw = 0.0;//當前揹包重量 current weight

double cp = 0.0;//當前揹包中物品總價值 current value

double bestp = 0.0;//當前最優價值best price

double perp[100];//單位物品價值(排序後) per price

int order[100];//物品編號

int put[100];//設定是否裝入,為1的時候表示選擇該組資料裝入,為0的表示不選擇該組資料

//按單位價值排序

void knapsack()

//如若左子節點可行,則直接搜尋左子樹;

//對於右子樹,先計算上界函式,以判斷是否將其減去

if(cw+w[i]<=c)//將物品i放入揹包,搜尋左子樹

if(bound(i+1)>bestp)//如若符合條件則搜尋右子樹

backtrack(i+1);

}//計算上界函式,功能為剪枝

double bound(int i)

//裝滿揹包

if(i<=n)

b+=v[i]/w[i]*leftw;

return b;//返回計算出的上界

}int main()

*/ printf("請依次輸入%d個物品的重量:\n",n);

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

printf("請依次輸入%d個物品的價值:\n",n);

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

knapsack();

backtrack(1);

printf("最優價值為:%lf\n",bestp);

printf("需要裝入的物品編號是:");

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

return 0;

}

回溯法 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個 ...