分支界限法(Branch and Bound)-問(wèn)題1: 0/1背包客問(wèn)題

本范例主要是通過(guò)分支界限法解決著名的0/1背包客問(wèn)題


問(wèn)題描述:
N=4件商品,記為A,B,C,D,E把敞。每件商品的重量和價(jià)值分別為w[i]v[i];
其中w=[1.98,2,5,3.4], v=[100,40,95,50]
現(xiàn)在有一個(gè)背包幻妓,可以容納的最大重量為W=10疆偿。
問(wèn)該背包可以包含的最大價(jià)值是多少易遣?

基本思路:
本問(wèn)題是一個(gè)典型的排列組合問(wèn)題彼妻,只要能滿足總重量小于背包的容量的所有組合中,找到那個(gè)價(jià)值最大的組合;

每一件商品都有2種選擇侨歉,要么包含該商品屋摇,要么不包含該商品
因此總共有2^N種組合方式。當(dāng)N很大時(shí)幽邓,如果嘗試每一種組合方式炮温,將會(huì)使得計(jì)算量變得非常大。如下圖所示

上圖中每一個(gè)小圓圈都代表一個(gè)節(jié)點(diǎn)牵舵,對(duì)于每一個(gè)小節(jié)點(diǎn)柒啤,都擁有兩個(gè)分支,兩種選擇畸颅,即包不包含某一個(gè)商品担巩,這既是分支界限法種分支的由來(lái)。而界限是指我們做每一個(gè)選擇時(shí)没炒,我們先提前預(yù)估一下加入做了該選擇涛癌,可能出現(xiàn)的最優(yōu)或最差情況,即所謂的上界和下界

比如我們從零開(kāi)始送火,我們算一下最大價(jià)值是多少拳话?按照貪婪算法思想,我們商品已由單位重量?jī)r(jià)值進(jìn)行了從大到小的排列

那么開(kāi)始最大可能價(jià)值就是A,B,C全部包含种吸,D商品部分包含V_{max} =100+40+95+(10-1.98-2-5) *50/3.4 = 250, 由于可以包含部分商品弃衍,因此本價(jià)值提供了可能最大價(jià)值的上限。

假如包含商品A坚俗,則上限還是250镜盯,假如不包含商品A,則上限計(jì)算應(yīng)是B坦冠,C的全部?jī)r(jià)值加D部分價(jià)值形耗,應(yīng)該是
40+95+(10-2-5)*50/3.4=179.12

分支界限法的思想就是不斷選擇那個(gè)預(yù)測(cè)值最大的路哥桥,像上述包含商品A預(yù)測(cè)值大于不包含商品A的情況辙浑,因此,我們暫時(shí)選擇包含商品A拟糕,下一步就可以考慮是否包含商品B判呕,計(jì)算方法類(lèi)似

更換路線條件:
按照上述方法就為沿著一條路線不斷前進(jìn)且在岔路口選擇是否包含某一商品提供了一種判斷方法,那么什么情況得更換線路呢送滞?

  1. 重量超標(biāo)的情況侠草,本例中,假如每一條路線重量超過(guò)了10犁嗅,則該路走不通了边涕,必須切換到當(dāng)前預(yù)測(cè)價(jià)值最大的那條線路。
  2. 預(yù)測(cè)值下降嚴(yán)重,已經(jīng)小于另一條線路上的預(yù)測(cè)值功蜓,這是應(yīng)更換到那條預(yù)測(cè)值大的線路上园爷,也就是說(shuō)時(shí)刻走預(yù)測(cè)值最大的那條線路

結(jié)束條件:

  • 每一件商品都考慮到了,如何此時(shí)還是最優(yōu)的情況式撼,那么這條線路就一定是最優(yōu)的情況童社,如本例中就是包含商品A,B著隆,C扰楼,不包含商品D,最大價(jià)值是235


python代碼

"""
Created on Mon Jan  7 21:57:42 2019

@author: WAY
"""

from copy import copy,deepcopy
class Item:
    def __init__(self,w,v):
        self.w = w
        self.v = v
        self.r = v/w
    def __lt__(self,other):
        return self.r<other.r

class Node:
    def __init__(self):
        self.layer = -1
        self.info=[]
        self.optimum_value = -1
        self.total_weight=0
    def __lt__(self,other):
        return self.optimum_value<other.optimum_value


class Knapsack:
    def __init__(self,N,maxweight):
        self.N=N
        self.items = []
        self.max_weight = maxweight
        self.max_value = 0
        self.quene = []
    def add_item(self,item):
        self.items.append(item)
    def sort_item(self):
        self.items.sort()
        self.items.reverse()
    def calculate_matrix_value(self,node):
        weight = 0
        value = 0
        for i in node.info:
            weight += i.w
            value += i.v
        if weight>self.max_weight:
            node.optimum_value = -1
            return
        node.total_weight=weight
        for j in range(node.layer+1,self.N):
            if weight + self.items[j].w <= self.max_weight:
                weight += self.items[j].w
                value += self.items[j].v
            else:
                value += self.items[j].r*(self.max_weight-weight)
                break
        node.optimum_value = value
    def knapsack(self):
        node = Node()
        self.calculate_matrix_value(node)
        self.max_value = node.optimum_value
        self.quene.append(node)
        panduan = 0
        while self.quene:
            if panduan == 0:
                node = self.quene.pop()
            panduan=1
            node_L = deepcopy(node)
            node_L.layer += 1
            node_L.info.append(self.items[node_L.layer])
            self.calculate_matrix_value(node_L)
            if node_L.optimum_value>0  and node_L.optimum_value <=self.max_value:
                self.quene.append(node_L)
            
            node_R = deepcopy(node)
            node_R.layer += 1
            self.calculate_matrix_value(node_R)
            if node_R.optimum_value>0  and node_R.optimum_value <=self.max_value:
                self.quene.append(node_R)
            self.quene.sort()
            node = self.quene.pop()
            
            if node.layer == 3:
                break
        return node

def main():
    item1 = Item(2,40)
    item2 = Item(3.14,50)
    item3 = Item(1.98,100)
    item4 = Item(5,95)
    k = Knapsack(4,10)
    k.add_item(item1)
    k.add_item(item2)
    k.add_item(item3)
    k.add_item(item4)
    k.sort_item()
    nn = k.knapsack()
    print(nn.optimum_value)
    print(nn.total_weight)
    for i in nn.info:
        print(i.w)


if __name__ == "__main__":
    main()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市美浦,隨后出現(xiàn)的幾起案子弦赖,更是在濱河造成了極大的恐慌,老刑警劉巖浦辨,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腾节,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡荤牍,警方通過(guò)查閱死者的電腦和手機(jī)案腺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)康吵,“玉大人劈榨,你說(shuō)我怎么就攤上這事』耷叮” “怎么了同辣?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)惭载。 經(jīng)常有香客問(wèn)我旱函,道長(zhǎng),這世上最難降的妖魔是什么描滔? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任棒妨,我火速辦了婚禮,結(jié)果婚禮上含长,老公的妹妹穿的比我還像新娘券腔。我一直安慰自己,他們只是感情好拘泞,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布纷纫。 她就那樣靜靜地躺著,像睡著了一般陪腌。 火紅的嫁衣襯著肌膚如雪辱魁。 梳的紋絲不亂的頭發(fā)上烟瞧,一...
    開(kāi)封第一講書(shū)人閱讀 51,198評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音染簇,去河邊找鬼燕刻。 笑死,一個(gè)胖子當(dāng)著我的面吹牛剖笙,可吹牛的內(nèi)容都是我干的卵洗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼弥咪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼过蹂!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起聚至,我...
    開(kāi)封第一講書(shū)人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤酷勺,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后扳躬,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體脆诉,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年贷币,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了击胜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡役纹,死狀恐怖偶摔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情促脉,我是刑警寧澤辰斋,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站瘸味,受9級(jí)特大地震影響宫仗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜旁仿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一藕夫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧丁逝,春花似錦汁胆、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)誉尖。三九已至罪既,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背琢感。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工丢间, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人驹针。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓烘挫,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親柬甥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子饮六,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 專(zhuān)業(yè)考題類(lèi)型管理運(yùn)行工作負(fù)責(zé)人一般作業(yè)考題內(nèi)容選項(xiàng)A選項(xiàng)B選項(xiàng)C選項(xiàng)D選項(xiàng)E選項(xiàng)F正確答案 變電單選GYSZ本規(guī)程...
    小白兔去釣魚(yú)閱讀 8,985評(píng)論 0 13
  • 目錄 1.問(wèn)題描述1.1 問(wèn)題描述1.2 問(wèn)題的數(shù)學(xué)表示(規(guī)劃類(lèi)問(wèn)題臂外,此種表示可以轉(zhuǎn)換為回溯法)1.3 三種方法的...
    王偵閱讀 19,270評(píng)論 0 2
  • 選擇題部分 1.(),只有在發(fā)生短路事故時(shí)或者在負(fù)荷電流較大時(shí),變流器中才會(huì)有足夠的二次電流作為繼電保護(hù)跳閘之用窟扑。...
    skystarwuwei閱讀 12,897評(píng)論 0 7
  • 問(wèn)題描述: 0-1背包問(wèn)題:給定n種物品和一背包。物品 i 的重量似乎 wi漏健,其價(jià)值為 vi嚎货,背包的容量為 c。問(wèn)...
    我沒(méi)有三顆心臟閱讀 52,748評(píng)論 31 154
  • 最近真正的頹廢蔫浆,頹了一個(gè)星期啦厂抖。每天煩悶,和天氣一樣克懊,dreary!!! 本周要開(kāi)始工作忱辅,只是不知從何下手。抽了一...
    被地產(chǎn)耽誤的columnist閱讀 269評(píng)論 0 0