演算法0 1揹包問題

2021-10-10 22:19:44 字數 1811 閱讀 6384

演算法描述

0-1揹包問題是子集選取問題。一般情況下,0-1揹包問題是np難的。0-1揹包問題的解空間可用子集樹表示。解0-1揹包問題的回溯法與裝載問題的回溯法十分類似。在搜尋解空間樹時,只要其左兒子結點是乙個可行結點,搜尋就進入其左子樹。當右子樹有可能包含最優解時才進入右子樹搜尋;否則將右子樹剪去。設r是當前剩餘物品價值總和;cp是當前價值;bestp是當前最優價值。當ep+r<=bestp時,可剪去右子樹。計算右子樹中解的上界的更好方法是將剩餘物品依其單位重量價值排序,然後依次裝入物品,直至裝不下時,再裝入該物品的一部分而裝滿揹包。由此得到的價值是右子樹中解的上界。

例如,對於0-1揹包問題的乙個例項,n=4,c=7,p=[9,10,7,4],w=[3,5,2,1]。這4個物品的單位重量價值分別為[3,2,3.5,4]。以物品單位重量價值的遞減順序裝入物品。先裝入物品4,然後裝入物品3和1。裝入這3個物品後,剩餘的揹包容量為1,只能裝入0.2的物品2。由此得到乙個解為x=[1,0.2,1,1],其相應的價值為22。儘管這不是乙個可行解,但可以證明其價值是最優值的上界。因此,對於這個例項,最優值不超過22。

為了便於計算上界,可先將物品依其單位重量價值從大到小排序,此後只要順序考查各物品即可。在實現時,由 bound 計算當前結點處的上界。類 knapsack 的資料成員記錄解空間樹中的結點資訊,以減少引數傳遞以及遞迴呼叫所需的棧空間。在解空間樹的當前擴充套件結點處,僅當要進人右子樹時才計算上界bound,以判斷是否可將右子樹剪去。進入左子樹時不需計算上界,因為其上界與其父結點的上界相同。

解0-1揹包問題的回溯演算法描述如下:

public

class

knapsack

public

intcompareto

(object x)

public

boolean

equals

(object x)

}static

double c;

//揹包容量

static

int n;

//物品數

static

double

w;//物品重量陣列

static

double

p;//物品價值陣列

static

double cw;

//當前重量

static

double cp;

//當前價值

static

double bestp;

//當前最優價值

public

static

double

knapsack

(double

] pp,

double ww,

double cc)

backtrack(1

);//回溯搜尋

return bestp;

}private

static

void

backtrack

(int i)

//搜尋子樹

if(cw+w[i]<=c)if(

bound

(i+1

)>bestp)

backtrack

(i+1);

//進入右子樹

}private

static

double

bound

(int i)

//裝滿揹包

if(i<=n)

bound+=p[i]

* cleft/w[i]

;return bound;

}}

演算法(揹包問題 01揹包問題)

01揹包問題 有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。第 i 件物品的體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品數量和揹包容積。接下來有 n 行,...

演算法 0 1揹包問題

揹包問題是演算法中的乙個經典問題,它有很多子問題,比如0 1揹包問題,完全揹包問題,多重揹包問題等等。而今天所說的0 1揹包問題的原始描述為 現在有n件物品和乙個最大承載重量為m的揹包,要從這n件物品中選擇其中的k 1 k n 件,使得所選擇的物品的價值總和最大且其總重量不超過揹包的最大載重量。這n...

演算法 01揹包問題

對於乙個物品,選擇放還是不放,只有兩個選擇,故屬於01問題.物品 public class item 第n件物品,放入剩餘容量為leftweight的揹包中所獲得的最大價值 static int getmaxvalue listlist,int n,int leftweight 如果當前n的容量超過...