洛谷 P3188 HNOI2007 夢幻島寶珠

2022-03-17 04:22:51 字數 2565 閱讀 4824

給你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

分析乍一看,怎麼又是揹包。

再一看,woc,範圍怎麼這麼大。

有一看,好像可以根據2的幾次冪來分層,最後合併。

仔細一想,還不是要很大的空間和複雜度,而且還不會寫。

再一想,千年等一回

最後放棄去網上找題解,結果發現有乙個貪心,從一位與下一位的合併時,只考慮這一位1000以內的情況。

用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)])

其中(2*k+((w>>(i-1))&1))可以通過倒推得到,用j*2^i+(w&((1<< i)-1))減去k*2^i+(w&((1<< i)-1))即可

upd 20191014

突然想到一種對dp轉移式子的感性理解,第i位的k到第i-1位後就是k*2,而((w>>(i-1) )&1)就代表w在第i-1位是否有1

所以dp轉移式子還可以優化成

dp[i][j]=max(dp[i][j],dp[i][j-k]+max(dp[i-1][2*k+((w>>(i-1) )&1)],dp[i-1][2*k]))

順便把另一種寫法也寫了。。。。。。

推薦乙個部落格

好像物品可以乙個乙個加進去,時間上會有很大的優化,然而並不會寫。

**(不要在意那個o2)

#pragma gcc optimize (2)#include

#include

#include

using

namespace

std;

int n,m,cnt,i,j,k,w,val,f[35][1005

];int

main()

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

]); }

}

#include#include

#include

using

namespace

std;

long

long f[50][3005

];int n,m,st[50][105][2

];int

main()

int lim=0;for(int i=m/2;i;i/=2)lim++;

for(int i=0;i<=lim;i++)

printf(

"%lld\n

",f[lim][1

]); }

}

洛谷 P3188 HNOI2007 夢幻島寶珠

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

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的物品時,乙個容量...