演算法的經典問題之一揹包問題,揹包問題是動態規劃(運籌學)的乙個典型的例子,它的問題描述即規定揹包所能容納的最大重量,然後此時有一批物品對應不同的質量和價值,那麼如何放置物品進入揹包使得揹包中的價值最大。
通常情況下,揹包問題會分為兩種情形:
前一種情況,只能用貪心演算法解決去解決問題。後一種情況,則需要通過動態規劃。
首先,我們先來認識一下動態規劃解決問題的步驟:
然後假設此時我們有乙個這樣的揹包問題:
此時有乙個揹包可容納的重量為 7,分別有重量為 2、3、4 對應價值為 3、4、5 的三個物品 ,並分別命名為物品 1、物品 2、物品 3。要如何往揹包中放置物品,才能使得揹包中的價值最高?對於從事程式設計的同學而言,遇到略顯複雜的問題,我們應該先建立數學模型。而對於這個揹包問題,它的數學模型是這樣的:
揹包所能容納的重量 w:5
物品 重量 價值12
3234
345(矩陣的行數為物品數量+
1,列為揹包所能容納重量+
1,初始化預設 0 列 0 行為 0
)第一階段
i/w 012
3450
0000
0010
0333
3203
0第二階段
i/w 012
3450
0000
0010
0333
3200
3447
3003
457(最**值)
可以看出對於我們這個揹包問題,只需要兩個階段就可以放入揹包的物品最**值。但是,我們還需要找出對應價值的物品(這個過程就不建模了,比較簡單,直接看**)。
/*
capacity 揹包所能容納的最大重量
n 物品的數量
ks 最優方案對應的矩陣
weights 物品對應的重量陣列
values 物品對應的價值陣列
*/function
findgoods
(n, capacity, ks, weights, values)
可以是解的一部分, 重量:
$, 價值:$`
) i--
k -= ks[i]
[k]}
else
}}
既然,我們已經寫好揹包問題的數學模型,以及準備好尋找對應價值的物品的函式。接下來,就把揹包問題對應數學模型的演算法實現:
/*
capacity 揹包所能容納的最大重量
weights 物品對應的重量陣列
values 物品對應的價值陣列
n 物品的數量
*/function
knapsack
(capacity, weights, values, n)
for(
let i =
0; i <= n; i++
)else
if(weights[i -1]
<= w)
else}}
findgoods
(n, capacity, ks, weights, values)
return ks[n]
[capacity]
}
這個演算法其實非常簡單,正如我們前面描述的數學模型一樣,矩陣中滿足約束條件 weights[i - 1] <= w 的進行相應的計算,然後對比矩陣此時索引中上一行對應列的值,誰大此時對應索引值就為誰。反正,如果不滿足約束條件,就取矩陣此時索引中上一行對應列的值。
對於揹包問題的分數版,動態規劃就無能為力了。這個時候,就需要用貪心演算法解決,先來看看貪心演算法的定義。貪心演算法是一種近似解決問題的技術,通過每個階段的區域性最優解,從而達到全域性最優解的效果。簡單地理解,就是類似於歸納法推出符合大多數情況下公式,然後通過這個公式求解。
function
knapsack
(capacity, weights, values)
else
return val
}}
對比動態規劃的揹包問題,貪心演算法不僅貪心(簡潔)而且更易理解,只要我此時揹包剩餘的空間能容納下這個物體我就放進去,不能那我就放這個物體的一部分。 1469 資料結構 簡單揹包問題
本題難點 簡單揹包問題遞迴程式的理解 簡單揹包問題 問題定義 有乙個揹包重量是s,有n件物品,重量分別是w0,w1.wn 1 問能否從這n件物品中選擇若干件放入揹包中使其重量之和正好為s 揹包問題遞迴版本 解釋 其選擇只有兩種可能,選擇一組物品中包含wn 1 此時knap s,n 的解就是knap ...
資料結構與演算法 之01揹包問題
有一些物品,每種物品有各自的價值和代價,問給定代價之內選一些物品可以得到多少價值 有n件物品和乙個最大重量為v的揹包。第i件物品的重量是c i 價值是w i 求解將哪些物品裝入揹包可以使揹包價值總和最大,每種物品最多只能選一次 動態規劃 時間複雜度 o nv 空間複雜度 o v dp i j 表示只...
資料結構筆記 46 動態規劃(01揹包問題)
下面是演算法的介紹 先看乙個例項 揹包問題 輸出 package com.huey.dynamic public class knapsackproblem 物品的重量 int val 物品的價值 這裡的val i 就是前面講的v i int m 4 揹包的容量 int n val.length 物...