回溯法 0 1揹包問題(C 實現)

2021-09-24 16:42:05 字數 1689 閱讀 9809

概念:

回溯法是一種非常有效的方法,有「通用的解題法」之稱。它有點像窮舉法,但是更帶有跳躍性和系統性,他可以系統性的搜尋乙個問題的所有的解和任一解。回溯法採用的是深度優先策略。

三個步驟:

針對所給問題,定義問題的解空間;

確定易於搜尋的解空間結構;

以深度優先的方式搜尋解空間。

優化方法:

搜尋過程使用剪枝函式來為了避免無效的搜尋。剪枝函式包括兩類:

使用約束函式,剪去不滿足約束條件的路徑;

使用限界函式,剪去不能得到最優解的路徑。

解空間樹分為兩種:子集樹和排列樹。兩種在演算法結構和思路上大體相同。

所給的問題是從n個元素的集合s中找出滿足某種性質的子集時,相應的解空間成為子集樹。

如0-1揹包問題,從所給重量、價值不同的物品中挑選幾個物品放入揹包,使得在滿足揹包不超重的情況下,揹包內物品價值最大。它的解空間就是乙個典型的子集樹。

回溯法搜尋子集樹的演算法正規化如下:

void backtrack (int t)  

}

所給的問題是確定n個元素滿足某種性質的排列時,相應的解空間就是排列樹。

如旅行售貨員問題,乙個售貨員把幾個城市旅行一遍,要求走的路程最小。它的解就是幾個城市的排列,解空間就是排列樹。

回溯法搜尋排列樹的演算法正規化如下:

void backtrack (int t)  

}

0-1揹包問題

問題:給定n種物品和一揹包。物品i的重量是wi,其價值為pi,揹包的容量為c。問應如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大?

**如下:

#include using namespace std;

#define n 100   //預設有99個物品。第乙個不使用

int w[n];    //每個物品的重量

int v[n];    //每個物品的價值

int x[n];     //x[i]=1:物品i放入揹包,0代表不放入

int n,c;       //n:一共有多少物品,c:揹包的最大容量

/**curweight 和 curvalue儲存當前放入揹包的資料,隨著對解空間的不斷深入而變化

*/int curweight = 0;  //當前放入揹包的物品總重量

int curvalue = 0;   //當前放入揹包的物品總價值

/**bestvalue 和 bestx在找到乙個葉子節點時進行 約束函式 判斷,滿足的話就連同修改儲存的最優解

*/int bestvalue = 0;  //最優值;當前的最大價值,初始化為0

int bestx[n];       //最優解;bestx[i]=1代表物品i放入揹包,0代表不放入

void input()

cout

}void output()

}else

else //放入揹包}}

}}int main(int argc, char* ar**)

程式執行結果:

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