有依賴的揹包問題 華為機試 購物單 。動態規劃

2021-10-04 16:18:00 字數 3601 閱讀 5354

今天刷到一道有依賴的揹包問題,是牛客的華為機試題,記錄下解法。題目如下:

王強今天很開心,公司發給n元的年終獎。王強決定把年終獎用於購物,他把想買的物品分為兩類:主件與附件,附件是從屬於某個主件的,下表就是一些主件與附件的例子:

主件 附件

電腦 印表機,掃瞄器

書櫃 圖書

書桌 檯燈,文具

工作椅 無

如果要買歸類為附件的物品,必須先買該附件所屬的主件。每個主件可以有 0 個、 1 個或 2 個附件。附件不再有從屬於自己的附件。王強想買的東西很多,為了不超出預算,他把每件物品規定了乙個重要度,分為 5 等:用整數 1 ~ 5 表示,第 5 等最重要。他還從網際網路上查到了每件物品的**(都是 10 元的整數倍)。他希望在不超過 n 元(可以等於 n 元)的前提下,使每件物品的**與重要度的乘積的總和最大。

設第 j 件物品的**為 v[j] ,重要度為 w[j] ,共選中了 k 件物品,編號依次為 j 1 , j 2 ,……, j k ,則所求的總和為:

v[j 1 ]*w[j 1 ]+v[j 2 ]*w[j 2 ]+ … +v[j k ]*w[j k ] 。(其中 * 為乘號)

請你幫助王強設計乙個滿足要求的購物單。

顯然是一道有依賴的揹包問題,我們可以將其轉為分組揹包為題求解。

對於上述題目,a1,a2依賴於a,b1,b2,b3依賴於b,其中a,b稱為主件,a1,等為附件,若主件個數為n,我們可以將所有物品分為n個類別,每一類別是該主件與其附件的所有可能組合情況。例如對a類來說,我們將[a,(a,a1),(a,a1,a2),(a,a2)]歸為一類,類似這樣一共分成n個類別,就變成了分組揹包問題。

輸入資料,第一行為錢數,物件總數,以後各行分別為每件物品的**,重要程度,和依賴關係。0表示其為主件,其他數字表示其依賴於xx

1000 5

800 2 0

400 5 1

300 5 1

400 3 0

500 2 0

這一段**是讀入上面的資料,將其處理成

last_imp=[[

0],[

0,1600

,3600

,5100

,3100],

[0,1200],

[0,1000]]

,last_price=[[

0],[

0,800,

1200

,1500

,1100],

[0,400],

[0,500]]

.last_imp可以看成是01揹包中的價值。last_price是01揹包中重量

也可以自己處理成想要的格式,我處理的比較亂還沒有整理。反正就是為了得到上面的格式。

每個前面加個0是為了空出下標為0的行和列。

n,cycle=

list

(map

(int

,input()

.split())

)price =[0

]*cycle

imp =[0

]*cycle

rely =[0

]*cycle

for i in

range

(cycle)

: price[i]

,imp[i]

,rely[i]

=list

(map

(int

,input()

.split())

)def

get_subset

(alist,primary)

: res =

[primary]

for i in

range

(len

(alist)):

for j in

range

(i,len

(alist)):

1]+primary)

return res

dependency =

dict()

for i in

range

(len

(rely)):

if rely[i]==0

: dependency[i+1]

=[]for i in

range

(len

(rely)):

if rely[i]!=0

: dependency[rely[i]]1

)last =

for k,v in dependency.items():

[k])

)v =

[price[i]

*imp[i]

for i in

range

(len

(imp))]

last_imp =[[

0]]last_price =[[

0]]flag =

for i in

range

(len

(last)):

imp_alist =[0

] price_alist =[0

]for j in

range

(len

(last[i]))

: imp_tmp =

0 price_tmp =

0for k in

range

(len

(last[i]

[j])):

imp_tmp +=v[last[i]

[j][k]-1

] price_tmp += price[last[i]

[j][k]-1

]

下面是根據上面的處理好的資料格式的**:就和01揹包一樣,在其基礎上加了個判斷,取每組的最大值。

def

group_pack

(last_imp,last_price,n)

: f =

for i in

range

(len

(last_price)):

[0for i in

range

(n+1)]

)for i in

range(1

,len

(last_price)):

for j in

range(1

,n+1):

max_value =

0for k in

range

(len

(last_price[i]))

:if j[k]:

tmp_val = f[i-1]

[j]else

: tmp_val = f[i-1]

[j-last_price[i]

[k]]

+ last_imp[i]

[k]if tmp_val >= max_value:

max_value = tmp_val

f[i]

[j]= max_value

return f[-1

][n]

華為機試 購物單 分組揹包

王強今天很開心,公司發給n元的年終獎。王強決定把年終獎用於購物,他把想買的物品分為兩類 主件與附件,附件是從屬於某個主件的,下表就是一些主件與附件的例子 主件附件 電腦印表機,掃瞄器 書櫃圖書 書桌檯燈,文具 工作椅無 如果要買歸類為附件的物品,必須先買該附件所屬的主件。每個主件可以有 0 個 1 ...

華為機試 購物單

輸入例子 1000 5 800 2 0 400 5 1 300 5 1 400 3 0 500 2 0 輸出例子 2200 解題思路 這是一道揹包問題。先考慮解決揹包問題,思路是這樣 比如說這道題目,給定總錢數n,共有m件商品可以購買,從這m件商品中選擇購買商品,使得購買商品的錢數不超過n,同時滿足...

華為機試 購物單

王強今天很開心,公司發給n元的年終獎。王強決定把年終獎用於購物,他把想買的物品分為兩類 主件與附件,附件是從屬於某個主件的,下表就是一些主件與附件的例子 主件附件 電腦印表機,掃瞄器 書櫃圖書 書桌檯燈,文具 工作椅無 如果要買歸類為附件的物品,必須先買該附件所屬的主件。每個主件可以有 0 個 1 ...