日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

完全背包问题从简单到复杂

發布時間:2024/9/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 完全背包问题从简单到复杂 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目

有 N 種物品和一個容量為 V 的背包,每種物品都有無限件可用。放入第 i 種物品的費用是 C i ,價值是 W i 。求解:將哪些物品裝入背包,可使這些物品的耗費的費用總和不超過背包容量,且價值總和最大。

第一種思路,基于投資問題模型

從每種物品的角度考慮,與它相關的策略已并非取或不取兩種,而是有取 0 件、取 1 件、取 2 件…直至取 ?V /C i ? 件等許多種。

狀態方程為:

F [i, v] = max {F [i ? 1, v ? kC i ] + kW i | 0 ≤ kC i ≤ v}

基于以上狀態方式實現的三種方式,遞歸,自上而下,自下而上如下:

# another way: F [i, v] = max {F [i ? 1, v ? kC i ] + kW i | 0 ≤ kC i ≤ v} def pack_complete_Rec2(N,V,C,W):if N ==0:return 0 k = V // C[N-1]result = -1for i in range(k+1):A = pack_complete_Rec2(N-1,V-i*C[N-1],C,W) + i*W[N-1]if A > result:result = Areturn result import numpy as np # 注意if list[N,V] == -1 的未知,因為它確定了剪枝; def pack_complete_Top_down2(N,V,C,W):list = np.zeros((N+1,V+1),dtype=int)list[1:,:] = -1def complete_Top_down(N,V):t = V // C[N-1] if list[N,V] == -1 :result = -1000for k in range(t+1):if N >=1:A = complete_Top_down(N-1,V-k*C[N-1]) + k*W[N-1]if A >= result:result = Alist[N,V] = result return list[N,V]return complete_Top_down(N,V) def pack_complete_Bottom_up2(N,V,C,W):list = np.zeros((N+1,V+1),dtype=int) # list[1:,:] = -1for i in range(1,N+1):for j in range(0,V+1):t = j // C[i-1]result = -1000for k in range(t+1):A = list[i-1,j-k*C[i-1]] + k*W[i-1]if A > result:result = Alist[i,j] = result return list[N,V]

把問題轉換成01背包問題,這里面涉及到等效或者泛化物品

將一種物品拆成多件只能選 0 件或 1 件的01背包中的物品,以下是簡單實現,基于二進制的實現,在多重背包中實現:

# change complete to 01 def change_complete_to_01(N,V,C,W):C_ =[]W_ =[]for i in range(N):t = V // C[i]for k in range(1,t+1):C_.append(C[i])W_.append(W[i])def pack_0_1_first(N,V,C,W): F =[0]*(V+1) for i in range(1,N+1):for v in range(V,C[i-1]-1,-1):F[v] = max(F[v],F[v-C[i-1]] + W[i-1])return F[V]N_ = len(C_)return pack_0_1_first(N_,V,C_,W_)

更為簡單的實現,把第i種物品看成一個整體,針對第i種物品就有2種策略,1不選:可以看成i-1的問題,二選,就可以看成第i類的01背包問題,因為V是一定的,此時的i實際上不是無限的,是受V限制的,就可以把有限的i看成不同的物品,等價于一個01背包問題,狀態方程如下:

F [i, v] = max (F [i ? 1, v], F [i, v ? C i ] + W i )

基于以上狀態方式實現的三種方式,遞歸,自上而下,自下而上如下:

def pack_complete_Rec(N,V,C,W):if N ==0:return 0if V < C[N-1]:return pack_complete_Rec(N-1,V,C,W)return max(pack_complete_Rec(N-1,V,C,W),pack_complete_Rec(N,V-C[N-1],C,W) + W[N-1]) import numpy as np def pack_complete_Top_down(N,V,C,W):list = np.zeros((N+1,V+1),dtype=int)list[1:,:] = -1def complete_Top_down(N,V):if list[N,V] == -1 and N >=1:A = complete_Top_down(N-1,V)if V < C[N-1]: return Aelse:list[N,V] = max(A,complete_Top_down(N,V-C[N-1])+W[N-1])return list[N,V]return complete_Top_down(N,V)def pack_complete_Bottom_up(N,V,C,W):list = np.zeros((N+1,V+1),dtype=int)list[1:,:] = -1for 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,j-C[i-1]]+W[i-1])return list[N,V]

基于一維數組的簡單的實現如下,對比上述的Bottom_up方法,使用一維數組實現,通過初始化,能夠有效避免,左邊的走法:

def pack_complete_first(N,V,C,W):def CompletePack(F,ci,wi):for v in range(ci,V+1):F[v] = max(F[v],F[v-ci] + wi)return FF =[0]*(V+1)for i in range(1,N+1):CompletePack(F,C[i-1],W[i-1])return F[V]

完全背包可行性問題,只取決于初始化,只有F[0,0]才為0時,才可以得到有效解。

def pack_complete_first_yes_or_no(N,V,C):def CompletePack_or(F,ci,wi):for v in range(ci,V+1):F[v] = F[v] or F[v-ci]return FF =[False]*(V+1)F[0] = Truefor i in range(1,N+1):CompletePack_or(F,C[i-1],W[i-1])return F[V]def pack_complete_Bottom_up_yes_or_no(N,V,C):list = np.zeros((N+1,V+1),dtype=bool)list[0,0] = Truefor 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] = A or list[i,j-C[i-1]]return list[N,V]

運行結果:

#%% N = 7 V = 77 C = [1,2,3,9,13,6,7,5] W = [1,2,9,7,5,11,6,14] #%% print pack_complete_first(N,V,C,W) print pack_complete_Rec(N,V,C,W) print pack_complete_Top_down(N,V,C,W) print pack_complete_Bottom_up(N,V,C,W) print pack_complete_first_yes_or_no(N,V,C) print pack_complete_Bottom_up_yes_or_no(N,V,C) print pack_complete_Rec2(N,V,C,W) print pack_complete_Top_down2(N,V,C,W) print pack_complete_Bottom_up2(N,V,C,W) print change_complete_to_01(N,V,C,W)227 227 227 227 True True 227 227 227 227

總結

以上是生活随笔為你收集整理的完全背包问题从简单到复杂的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。