有 n 件物品和乙個容量為 v 的揹包。放入第 i 件物品耗費的費用是 c i 1 ,得到
的價值是 w i 。求解將哪些物品裝入揹包可使價值總和最大。
f [i, v] = max
這裡的出口容易搞錯,出口可以從遞推方程成立條件來考慮
def
pack_0_1_rec2
(n,v,c,w)
:if n ==0:
return
0if v < c[n-1]
:return pack_0_1_rec(n-
1,v,c,w)
return
max(pack_0_1_rec(n-
1,v,c,w)
,pack_0_1_rec(n-
1,v-c[n-1]
,c,w)
+ w[n-1]
)
# 後來仔細考慮出後之後,做了如下修正:
defpack_0_1_top_down
(n,v,c,w)
:list=[
[-1]
*(v+1)
for i in
range
(n+1)]
# mins = min(c)
# for i in range(n+1):
# for j in range(v+1):
# if i == 0 or j< mins:
# list[i][j] =0
list[0
]=[0
]*(v+1
)def
pack_0_1_top_down_
(n,v)
:# if list[n][v] == -1 and n >=1 and v >=mins:
iflist
[n][v]==-
1and n >=1:
a = pack_0_1_top_down_(n-
1,v)
if v < c[n-1]
:return a
else
:list
[n][v]
=max
(a,pack_0_1_top_down_(n-
1,v-c[n-1]
)+w[n-1]
)return
list
[n][v]
return pack_0_1_top_down_(n,v)
defpack_0_1_bottom_up
(n,v,c,w)
:list=[
[-1]
*(v+1)
for i in
range
(n+1)]
list[0
]=[0
]*(v+1
)for i in
range(1
,n+1):
for j in
range(0
,v+1):
a =list
[i-1
][j]
if j < c[i-1]
:list
[i][j]
= a
else
:list
[i][j]
=max
(a,list
[i-1
][j-c[i-1]
]+w[i-1]
)# print list
return
list
[n][v]
凡是基於去與不去的問題,均可使用如下方式
def
pack_0_1_first
(n,v,c,w)
:def
zeroonepack
(f,ci,wi)
:for v in
range
(v,ci-1,
-1):
f[v]
=max
(f[v]
,f[v-ci]
+ wi)
return f
f =[0
]*(v+1
)for i in
range(1
,n+1):
zeroonepack(f,c[i-1]
,w[i-1]
)return f[v]
可行性問題,想清楚初始條件
如果是,要求恰好裝滿揹包,那麼在初始化時除了 f [0] 為 0 ,其
它 f [1…v ] 均設為 −∞ ,這樣就可以保證最終得到的 f [v ] 是一種恰好裝滿揹包的最優解。
如果並沒有要求必須把揹包裝滿,而是只希望**盡量大,初始化時應該將 f [0…v ] 全部設為 0 。
這是為什麼呢?可以這樣理解:初始化的 f 陣列事實上就是在沒有任何物品可以放入揹包時的合法狀態。
如果要求揹包恰好裝滿,那麼此時只有容量為 0 的揹包可以在什麼也不裝且價值為 0 的情況下被「恰好裝滿」,
其它容量的揹包均沒有合法的解,屬於未定義的狀態,應該被賦值為-∞了。
如果揹包並非必須被裝滿,那麼任何容量的揹包都有乙個合法解「什麼都不裝」,這個解的價值為 0 ,
所以初始時狀態的值也就全部為 0 了。
def
pack_0_1_yes_or_no
(n,v,c)
:def
zeroonepack
(f,ci)
:for v in
range
(v,ci-1,
-1):
f[v]
= f[v-ci]
or f[v]
return f
f =[-
1]*(v+1)
f[0]
=true
for i in
range(1
,n+1):
zeroonepack(f,c[i-1]
)return f[v]
#%%
n =6
v =23
c =[1,
3,4,
5,17,
11]w =[2,
9,7,
5,11,
4]#%%print pack_0_1_rec(n,v,c,w)
print pack_0_1_first(n,v,c,w)
print pack_0_1_top_down(n,v,c,w)
print pack_0_1_bottom_up(n,v,c,w)
print pack_0_1_rec2(n,v,c,w)
print pack_0_1_yes_or_no(n,v,c)
2525
2525
25true
簡單0 1揹包問題
有乙個揹包能裝的重量maxw 正整數,0 maxw 20000 同時有n件物品 0 n 100 每件物品有乙個重量wi 正整數 和乙個價值pi 正整數 要求從這n件物品中任取若干件裝入揹包內,使揹包的物品價值最大。第1行 揹包最大載重maxv,物品總數n 第2行到第n 1行 每個物品的重量和價值 乙...
裝箱問題 簡單01揹包問題)
題目描述 description 有乙個箱子容量為v 正整數,0 v 20000 同時有n個物品 0 n 30 每個物品有乙個體積 正整數 要求n個物品中,任取若干個裝入箱內,使箱子的剩餘空間為最小。輸入描述 input description 乙個整數v,表示箱子容量 乙個整數n,表示有n個物品 ...
揹包問題 01揹包問題
n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...