揹包問題通俗的說,就是假如你面前有5塊寶石分別為a, b, c, d, e,每塊寶石的重量不同,並且每塊寶石所帶來的價值也不同(注意:這裡寶石的重量的價值沒有特定關係),目前我們有乙個揹包,只有固定的容量,要解決的問題就是在一定容量的揹包面前裝哪幾塊寶石才能獲取到最大的價值,對於每塊寶石我們只有拿或者不拿這兩種選擇,拿為1不拿為0,因此叫做0-1揹包問題,下面通過乙個例子來深入理解揹包問題
假設a, b, c, d, e五塊寶石的重量分別為為2, 2, 6, 5, 4,價值分別為6, 3, 5,4, 6 ,我們目前的揹包可以裝重量為10的物品,怎麼裝才能使得獲取的價值最大?
首先對於我們人去操作而言,首先考慮應該是質量最輕,並且價值最大的,從資料中我們可以看到寶石a質量最小,且價值最大,應該優先考慮裝這一塊,然後依次考慮其他的。這種方式就是考慮價效比最高的寶石。我們可以將這個問題進行簡化,目前是揹包承重為10,因此我們的選擇較多,不知從何下手,那麼我們假設揹包的承重為5或者是3甚至是2, 1。在這種情況下,我們的選擇就不多了,對於人類選擇也是,在選擇不多的情況下更容易找出最優方案,同樣計算機也是。因此我們的揹包問題也是從這開始,將選擇較多的問題轉化為選擇不多的問題。在選擇不多的情況下進行選擇,有利於比較判斷,依次遞增,最後解決揹包承重為10的問題。
對於揹包問題,其實是乙個動態規劃,對於動態規劃,大多數都是用乙個陣列來進行儲存,對於初學者而言,如果我直接給你個陣列公式,相信你看著也不太懂公式表示什麼,陣列怎麼來的,別著急,耐心看,下面就一步一步的解釋該陣列的資料是怎麼來的,公式是怎麼推導出來的,附**
首先我們假設揹包承重為0,當然一塊寶石都不能裝,同樣假設揹包承重為1,也是一塊寶石都不能裝。
接下來考慮承重為2的時候:
考慮寶石a,目前揹包容量為2,裝---價值為6,不裝----價值為0---->>選擇裝 價值為6, 容量為0
考慮寶石b,目前揹包容量為0,裝---(得空出2的容量,因此得拿出寶石a,放入寶石b)價值為3,不裝---價值為6---->>選擇不裝,價值為6,容量為0
對於寶石c, d, e來說,承重為2的揹包不足以裝下其中任意一塊寶石,不考慮,因此最終獲得解決方案為,裝寶石a,最大價值為6
難度公升級,考慮揹包承重為4(承重為3的時候,解決方案和承重為2的時思路一致,方案相同,不作敘述)
考慮寶石a,目前揹包容量為4,裝---價值為6,不裝---價值為0---->>選擇裝價值為6,容量為2
考慮寶石b,目前揹包容量為2,裝---(需要2的容量,足夠)價值為6+3=9,不裝---價值為6---->>選擇裝,價值為9,容量為0
考慮寶石c,目前揹包容量為0,裝---(需要6的容量),不考慮
考慮寶石d,目前揹包容量為0,裝---(需要5的容量),不考慮
考慮寶石e,目前揹包容量為0,裝---(需要4的容量,取出寶石a和b,放入寶石e),價值為4---->>選擇不裝,價值為9,容量為0
因此最終解決方案為裝入a和b
根據我們的解題思路,大家可以看到,在考慮一塊寶石需不需要裝入揹包的時候,是需要考慮裝入揹包時需要多少空間,而將揹包騰出這麼大的空間又要拿出價值多少的寶石,就是在放入寶石和拿出寶石之間做乙個價值比對,從而進行選擇。而我們之前存入的寶石及其價值就需要乙個陣列來進行儲存
寶石重量價值1
2345
6789
10a26
0669
9121215
1515b2
3033
6699
91011c
6500
0666
661011d5
4000
6666
61010e
4600
0666
6666
其中藍色區域為我們需要的二維陣列,填寫順序為從下到上,從左到右,以第一列為例,此時揹包承重為1,依次考慮寶石e, d, c, b, a(這裡相比上面分析相比是倒序的,方便**的填寫以及效果**),當前的最大價值為0,當隨著揹包承重在增加,我們依照上述步驟進行分析
以揹包承重為8進行分析(非常重要!!!!!!!)
考慮寶石e,目前揹包容量為8,裝----價值為6,不裝----價值為0,選擇裝,因此**8e對應為6
考慮寶石d,裝----需要5的空間,還剩餘3的空間,因此檢視在揹包容量為3的時候,且只有e寶石,最大價值為0,加上d的價值為4,總價值為4,不裝-----價值為6,因此不裝,8d值為6
考慮寶石c,裝---需要6的空間,還剩餘2的空間,因此檢視揹包容量為2的之後,且只有寶石e和d,最大價值為0.加上c的價值為5,總價值為5,不裝-----價值為6,因此不裝,8c為6
考慮寶石b,裝---需要2的空間,還剩餘6的空間,因此檢視揹包容量為6時,只有寶石e、d和c,最大價值為6,加上b的價值為3,總價值為9,不裝--價值為6,因此裝,8b為9
考慮寶石a,裝---需要2的空間,還剩餘6的空間,因此檢視揹包容量為6時,只有寶石e、d、c和b,最大價值為6,加上a的價值為6,總價值為12,不裝---價值為9,因此裝,8a為12
在此處分析需要注意兩點:
1. 需要預先給寶石排好順序,依次考慮
2.**填寫順序,需要先考慮揹包容量小時,因為大容量揹包需要用到小容量揹包時的資料(陣列要依次填充)
根據上述分析,我們來確定揹包問題中的數學公式,假設每種寶石的重量分別為
其中max函式中的第一項表示,不裝第i個寶石的情況,第二項表示裝第i個寶石,就需要考慮總揹包容量減少w[i],然後總價值加上當前v[i]。
public int testpack(int weight, int value, int cap)
int len = weight.length;
int f = new int[len][cap + 1];//cap+1因為給定容量為cap,因此j的迴圈必須到cap
for(int j = 1; j < cap + 1; j++)else
}elseelse }}
}return f[len - 1][cap];
}@test
public void test();
int value = new int ;
int cap = 10;//可修改對應**進行驗證
system.out.println(testpack(weight, value, cap));//輸出為**中對應資料
}
希望對初學者有所幫助,歡迎批評指 一步一步 Sql Azure
一步一步 sql azure 1.使用 windowsazure 平台賬號登陸 2.新建sqlazure server 3.新建資料庫 4.為sql azure server 新增防火牆規則,只有將本機新增到規則裡才能從本機連線到該sqlazure server 5.連線到sql azure ser...
一步一步學cscope
告之 1,我不喜歡寫部落格 因為感覺太浪費時間 2,部落格能記住自己某階段學過的東西,而這些東西可能會很快的忘卻 所以我以後要學著在部落格上浪費時間 前言 本文件記錄了我今天 2007 11 9 下午學習cscope的一點收穫,特收錄部落格以作分享。在學習cscope過程中查閱了大量的文件,但發現適...
走一步,再走一步
時光如梭,匆匆流逝的所有,讓我再一次懂得了,人生的時光門票,在不斷的穿梭過去和未來,也任光陰的手撫摸著這個現在,有太多的好像,早已和我的過去劃開了界限,無論悲傷的過往,還是美好而快樂過的曾經,都好像已經不重要了。重要的是,走一步,再走一步。這場在歲月裡一直奔跑的故事,和那始終無法為自己畫上成功圓滿的...