題目描述
給你n顆寶石,每顆寶石都有重量和價值。要你從這些寶石中選取一些寶石,保證總重量不超過w,且總價值最大為
,並輸出最大的總價值。
資料範圍:n<=100;w<=2^30
,並且保證每顆寶石的重量符合a*2^b(a<=10;b<=30)
輸入格式
輸入檔案中包含多組資料。
每組資料的格式如下:
第一行是兩個正整數n和w,1≤n≤100,1≤w≤2^30,分別表示寶石的數目和最多能帶走的寶石重量。
接下來的n行,每行有兩個正整數weighti和valuei,1≤weighti≤2^30, 0≤valuei≤2^30,
分別表示第i顆寶石的重量和價值,且保證weighti能寫成a*2^b(1≤a≤10,0≤b≤30)的形式。
同一行的兩個正整數之間用空格隔開。
最後一組資料的後面有兩個-1,表示檔案的結束。這兩個-1並不代表一組資料,
你不需對這組資料輸出結果。並且輸入檔案中資料的組數不超過20。
輸出格式
對於輸入的每組資料,輸出乙個整數c,表示小p最多能帶走的寶石的總價值。
每個結果整數c單獨佔一行,且保證c不會超過2^30。
輸入樣例
4 10
8 95 8
4 62 5
4 13
8 95 8
4 62 5
16 75594681
393216 5533
2 77
32768 467
29360128 407840
112 68
24576 372
768 60
33554432 466099
16384 318
33554432 466090
2048 111
24576 350
9216 216
12582912 174768
16384 295
1024 76
-1 -1
輸出樣例
1419
1050650
分析用dp[i][j]表示揹包的容量已經占用了j*2^i+(w&((1<< i)-1))時的最大價值
先對於每乙個i進行揹包的合併,然後再考慮把每一位合併。
合併時,dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[i-1][2*k+((w>>(i-1) )&1)])
其中(2k+((w>>(i-1))&1))可以通過倒推得到,用j2^i+(w&((1<< i)-1))減去k*2^i+(w&((1<< i)-1))即可
**
#pragma gcc optimize (2)
#include
#include
#include
using
namespace std;
int n,m,cnt,i,j,k,w,val,f[35]
[1005];
intmain()
int lim=0;
for(i=m;i;i/=2
)lim++
;lim--
;for
(i=1
;i<=lim;i++
)for
(j=min
(1000
, m>>i)
;j>=
0;j--
)for
(k=0
;k<=j;k++
) f[i]
[j]=
max(f[i]
[j],f[i]
[j-k]
+f[i-1]
[min
(1000
,(k*2)
|((m>>
(i-1))
&1))
]);printf
("%d\n"
,f[lim][1
]);}
}
洛谷 P3188 HNOI2007 夢幻島寶珠
給你n顆寶石,每顆寶石都有重量和價值。要你從這些寶石中選取一些寶石,保證總重量不超過w,且總價值最大為 並輸出最大的總價值。資料範圍 n 100 w 2 30,並且保證每顆寶石的重量符合a 2 b a 10 b 30 輸入檔案中包含多組資料。每組資料的格式如下 第一行是兩個正整數n和w,1 n 10...
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 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的物品時,乙個容量...