揹包問題,相信各位看官肯定都有所耳聞!筆者就在此簡單的描述一下揹包問題:
給定一揹包和n件物品,揹包的容量為c,第i件物品的重量為w[i],價值為v[i](1<=i<=n);問裝那些物品,可使得價值最大?
思路分析:顯然,每種物品不外乎兩種選擇:裝入和不裝入揹包!若將裝入用狀態1表示,不裝入用狀態0表示;那麼就可構成乙個二叉樹!一共有n層,所以就可通過從第一層開始遍歷搜尋,在裝入的物品總重量不大於c的情況下,找到最優解了!
思路還是蠻簡單的,別的不多說,直接上**:
publicclass
demo1
;//每個物體的重量:5個物體
private
staticint
v =;//每個物體的價值
private
staticint
x=newint[6
];//存放每個物體的選中情況
private
static
intbestcp =0
;//當前的最優解
private
staticint
bestcparr
=new
int[6];
private
static
intcount =0
;private
static
intn =5
;//物體的數目
public
static
void
main
(string
args
)system
.out
.println(""
);system
.out
.println
(bestcp
);system
.out
.println
("該樹有"
+count
+"種遍歷方式");}
/***
* @param i:查詢到了第i個物品(i從1開始索引)
* @param cv:當前包中價值
* @param cw:當前包中重量
*/private
static
void
backtrack
(inti ,
intcw
,intcv)
}}else}}
}}
我們知道,回溯法的效率並不是很高的!因為回溯法,就其本質而言,還是屬於窮舉!只不過它就提供了乙個窮舉的思路:回溯!的確也是這樣,上面**中的例子中的物品只由5個,換句話說,所構成的二叉樹也只有5層!但當物品有10個,20個,甚至100個話,構成的二叉樹是多麼的龐大!(筆者覺得不可想象深度為100的二叉樹)!故在上述**的基礎上,很有必要去做乙個演算法的優化!在網上看了別人的部落格之後,大致知道了乙個思路:即在不斷的遍歷左子樹(即不斷的將物品裝入)的過程中,如果出現了不能再裝入下一物品的情況時,這時就需要去遍歷右子樹!但是如果,如果在剩餘容量情況下,將剩餘容量的揹包裝滿(如果大於0且小於物品的重量的話,按照單位重量的價值乘以剩餘容量來算)的情況下 得到的總價值比當前最優解還要的小的話,那麼該右子樹是完全沒有必要去遍歷,而需要直接剪除的!這樣就達到了優化的目的!廢話不多說,直接上**:
/***本演算法的上界函式是這樣定義的!首先利用冒泡法排序,按照單位價值右高到低開始順序排列!
*這樣的話,就能保證,先裝進去的是價效比(自己發明的,勿噴)最優的!
而在上界函式中,也是如此,
求的是剩餘
*容量在右子樹所能容納的最**值(揹包容量允許情況下),一旦小於當前最優解,那麼就
*沒有繼續遍歷該右子樹的必要**/
public
class
demo2}}
// 回溯函式
private
static
void
backtrack
(inti)
// 將物品裝進揹包:此種情況的話if(
cw +w[
i]<=c)
if(bound(i
+1)>
bestp
)// 符合條件搜尋右子數
backtrack(i
+1);}
// 計算上界函式
//演算法剩餘容量的情況下最多能裝的價值
private
static
double
bound
(inti)
if(i <=n)
b +=v[
i]/w
[i]*
leftw
;returnb;
}public
static
void
main
(string
args
); //每個物體的重量:5個物體
// private static int v = ; //每個物體的價值v[
0]=0
;v[1
]=6;
v[2]
=3;v
[3]=
5;v[
4]=4
;v[5
]=6;
w[0]
=0;w
[1]=
2;w[
2]=2
;w[3
]=6;
w[4]
=5;w
[5]=
5;n =
5;c =
10;knapsack
();backtrack(1
);system
.out
.println
(bestp
);for
(inti =
1;i <=n;
i++)
system
.out
.println(""
);}}
現在,我們來分析下時間複雜度,最好的情況當然是能夠剪除所有的右子樹,而最優的物品選擇剛好全在左子樹上了!而最壞的情況自然是搜尋右子樹的次數最多了呀!
到此,直接遍歷窮舉和優化之後的回溯法來解決10揹包問題的分析解答終於寫完了!寫了一上午啊!
筆者水平有限,望各位看官勿怪!
參考部落格:
優化的回溯法解決10揹包問題
遍歷的回溯法解決10揹包問題
演算法學習 01揹包問題
是慕課網的實戰演算法課程 動態規劃 相當於還是求n個物品的組合!暴力解法 每一件物品,都可以放進揹包,也可以不放進。複雜度是o 2 n n 對於每乙個組合,還要看看對應的總重是多少,看看是不是超過了容量c,從而看價值。組合方式都可以用遞迴的方式來求解。只是是能不能找到重疊子問題 最優子結構,從而轉換...
演算法學習筆記之基礎dp之(0 1)揹包問題
揹包問題 有多個物品,重量不同 價值不同,以及乙個容量有限的揹包,選擇一些物品撞到揹包中,問怎麼裝才能使裝進揹包的物品總價值最大。根據不同的的限定條件,可以報揹包問題分為很多種,常見的有下面兩種 如果每個物品可以切分,稱為一般揹包問題,用貪心法求最優解。比如吃自助餐,在飯量一定的情況下,怎麼吃才能使...
揹包問題之0 1揹包 二
問題描述 有n個物品,第i個物品的重量為w i 價值為v i 選一些物品放入揹包中,使揹包內物品總重量恰好為w的前提下,總價值盡量大。輸入 有多組測試資料,每組資料第一行為2個正整數,分別代表物品的個數n和揹包的容量w,接下來的n行,每行2個正整數,用空格隔開,分別代表物品的重量w和價值v,當n w...