P3188 HNOI2007 夢幻島寶珠 揹包

2021-10-24 18:26:05 字數 1615 閱讀 3672

n

nn個物品,大小為w

ww的揹包。

每個物品的大小可以表示為wi=

ai2b

iw_i=a_i2^

wi​=ai

​2bi

​,有價值v

iv_i

vi​。

求選擇一些物品不超過揹包的大小使得價值最大。

設先計算b

ib_i

bi​相同的物品,設fi,

jf_

fi,j

​表示只計算b=i

b=ib=

i的物品時,乙個容量為j∗2

ij*2^

j∗2i

時的揹包時的最大價值。

然後將多個揹包合併,設gi,

jg_

gi,j

​表示只計算b≤i

b\leq i

b≤i的物品時,容量為j∗2

i+w&

(2i−

1)

j*2^i+w\&(2^i-1)

j∗2i+w

&(2i

−1)時的最大價值。

然後有轉移方程gi,

j=ma

xg_=max\+g_\ \ \}

gi,j​=

max然後答案就是g30,

0g_

g30,0​

時間複雜度o(n

log⁡a∑

a)

o(n\log a\sum a)

o(nloga∑

a)

#include

#include

#include

#include

using

namespace std;

const

int n=

110;

int n,w,a[n]

,v[n]

,lim[n]

;int f[n]

[n*n]

,g[n]

[n*n]

;vector<

int> q[n]

;int

main()

for(

int i=

0;i<=

30;i++

)for

(int j=

0;j.size()

;j++

)for

(int k=lim[i]

;k>=a[q[i]

[j]]

;k--

) f[i]

[k]=

max(f[i]

[k-a[q[i]

[j]]

]+v[q[i]

[j]]

,f[i]

[k])

;for

(int i=

0;i<=lim[0]

;i++

)g[0

][i]

=f[0

][i]

;for

(int i=

1;i<=

30;i++

)printf

("%d\n"

,g[30][

0]);

}}

P3188 HNOI2007 夢幻島寶珠

傳送門 注意到 a,b 不大 考慮對每乙個 a 2 b 的 b 分別揹包 設 f i j 表示只考慮 b i 的物品時,容量為 j sum a 的最大價值 這個就是普通的 01 揹包 考慮把 f i j 之間合併起來,為了得到容量為 w 時的答案,我們要把 f 的含義稍微變化一下 變成 f i j ...

洛谷 P3188 HNOI2007 夢幻島寶珠

題目描述 給你n顆寶石,每顆寶石都有重量和價值。要你從這些寶石中選取一些寶石,保證總重量不超過w,且總價值最大為 並輸出最大的總價值。資料範圍 n 100 w 2 30 並且保證每顆寶石的重量符合a 2 b a 10 b 30 輸入格式 輸入檔案中包含多組資料。每組資料的格式如下 第一行是兩個正整數...

洛谷 P3188 HNOI2007 夢幻島寶珠

給你n顆寶石,每顆寶石都有重量和價值。要你從這些寶石中選取一些寶石,保證總重量不超過w,且總價值最大為 並輸出最大的總價值。資料範圍 n 100 w 2 30,並且保證每顆寶石的重量符合a 2 b a 10 b 30 輸入檔案中包含多組資料。每組資料的格式如下 第一行是兩個正整數n和w,1 n 10...