0 1揹包問題 分支限界法

2021-06-26 20:38:22 字數 3173 閱讀 5648

0-1揹包問題可描述為:n個物體和乙個揹包。對物體i,其價值為value,重量為weight,揹包的容量為w

。如何選取物品裝入揹包,使揹包中所裝入的物品總價值最大?

2.1 用到的資料結構

class goods //定義貨物資料型別

;class knapsack//揹包

2.2 演算法步驟1)定**空間。(x0 , x1,x2,x3…..xn),xi的值為true或false。

(i = 0,1,2,3….n)

2)確定解空間。問題的解空間描述了2^n種可能的解,採用乙個二叉滿樹組織,解空

間的深度為問題的規模。

3)搜尋解空間

a.約束條件。揹包中物品重量小於揹包容量。

b.限界條件。ncurrentvalue為當前揹包中物品價值,nmaxvalue之前揹包中裝

入的最大價值的物品。np = bound(i + 1),第i個物品之後的所有物品可裝

入揹包的最大價

值。要求:np + ncurrentvalue > nmaxvalue.

c.以廣度優先的方式進行搜尋.首先以根節點即第乙個物品開始搜尋.

int bound(int i)//限界函式

if (i < ngoodsnum)

return tempmaxvalue;

} void knapsack_0_1_branchandbound()

activenodes.push_back(new node(nullptr, false, 0,0,0));

node *curnode = nullptr;

node *prenode = nullptr;

int curid;

while (!activenodes.empty())

if (nmaxvalue < curnode->nvalue)//若此節點物品價值大於揹包中最大物品價值

}ncurrentvalue = curnode->nvalue;

ncurrentweight = curnode->nweight;

curid = curnode->id;

if (nmaxvalue >= bound(curid + 1))//剪枝

//判斷下個物品是否可加入佇列

if (ncurrentweight + goods[curid + 1].weight <= capacity)

activenodes.push_back(new node(curnode, false, ncurrentweight,ncurrentvalue,curid + 1));

} while (!diednodes.empty())

}

4.1 空間複雜性:限界函式為o(1),最壞情況下需搜尋2^(n +1) –2個節點,需o(2^n )個空間儲存節點,則演算法空間複雜性為o(2^n )。

4.2 時間複雜性:限界函式時間複雜度為o(n),而最壞情況有2^(n +1) – 2個節點,若對每個節點用限界函式判斷,則其時間複雜度為o(n2^n).而演算法中時間複雜度主要依賴限界函式,則演算法的時間複雜度為o(n2^n)。

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

const int nknapsackcap = 10;

class goods //定義貨物資料型別

;ostream& operator<

typedef vectorallgoods;//定義所有貨物資料型別

class node

~node() };

class knapsack

if (i < ngoodsnum)

return tempmaxvalue;

}public:

knapsack(allgoods &allgoods, int nknapsackcap) }

void sortbyuintvalue()

); }

void printgoods() }

void printresult()

}}

void knapsack_0_1_branchandbound()

activenodes.push_back(new node(nullptr, false, 0,0,0));

node *curnode = nullptr;

node *prenode = nullptr;

int curid;

while (!activenodes.empty())

if (nmaxvalue < curnode->nvalue)//若此節點物品價值大於揹包中最大物品價值

}ncurrentvalue = curnode->nvalue;

ncurrentweight = curnode->nweight;

curid = curnode->id;

if (nmaxvalue >= bound(curid + 1))//剪枝

//判斷下個物品是否可加入佇列

if (ncurrentweight + goods[curid + 1].weight <= capacity)

activenodes.push_back(new node(curnode, false, ncurrentweight,ncurrentvalue,curid + 1));

} while (!diednodes.empty())

}};//獲取物品資訊,此處只是將書上例子輸入allgoods

void getallgoods(allgoods &allgoods)

int main()

5.2 執行結果

注意:**中可能會用到c++11新特性,請在支援c++11標準的環境下編譯執行

(如vs2013)





分支限界法 0 1揹包問題

分支限界法類似於回溯法,也是在問題的解空間上搜尋問題解的演算法。一般情況下,分支限界法與回溯法的求解目標不同。回溯法的求解目標是找出解空間中滿足約束條件的所有解,而分支限界法的求解目標則是找出滿足約束條件的乙個解,或是在滿足約束條件的解中找出使某一目標函式值達到極大或極小的解,即在某種意義下的最優解...

0 1揹包問題(分支限界法)

需求分析 0.問題描述 給定一揹包的容量c,和n個物品的重量wi價值vi,求在揹包容量允許的條件下能裝入的最大價值 1.問題分析 解空間 子集樹,第i層每個節點有兩棵子樹 選擇物品i,不選擇物品i 優先佇列的優先順序如何確定?每個節點的祖先節點都已經確定,那麼可以得到已經裝入揹包的物品的價值,加上剩...

分支限界法01揹包問題 01揹包問題

1.01揹包問題的描述 有n個不可分割的物品,它們有各自的重量和價值,現有固定容量的揹包,選擇把哪些物品放入揹包可以讓揹包中物品的價值最大。2.錯覺 按照價值和重量的比值 價效比 進行排序,依次嘗試放入直到放不進揹包為止。但是細想思考一下就能發現,這個貪心演算法是有問題的,看下面乙個例子。揹包容量1...