給你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
這道題是經典問題揹包的變形
剛一看到題我立刻反應:這是揹包啊,水題!
後來看見了w<=2^30 tle mle 呵呵
我關注到有乙個 2^30 立刻想到以a*2^b b分層dp
f[i,j]表示體積為j*2^i再加上w二進位制第i位以下的體積最多可以獲得多少價值
每一層單獨dp一下,就是普通的01揹包
層與層之間還要dp一下
f[i,j]=max(f[i,j],f[i,j-k]+f[i-1,min(k*2+e[i-1],d[i-1])])
解釋一下,d[i]表示第i層最多到體積為d[i]*2^i,這個可以算出來,就是d[i]:=sum[i]+(d[i-1]+1)>>1,sum[i]是這一層的a的總和,d[i]就是用來減少不必要的運算的
那麼這樣就可以過了
#include #include #include #include #include #include using namespace std;
int n,s,x,y,k;
int sum[50],a[50],d[50];
int weight[50][110],value[50][110];
long long f[50][1010],ans;
int main()
a[k] ++;
weight[k][a[k]] = x;
value[k][a[k]] = y;
sum[k] += x;
} k = 1;
while(s > (1 << k - 1)) k ++;
k --;
printf("%d ",k);
for(int i = 0; i <= k; i ++)
printf("%lld\n",f[k][1]);
} return 0;
}
夢幻島寶珠
一道非常巧 e 妙 xin 的分層揹包dp題 最後吸氧強行過 發現大部分人都是這樣過的.解析不想寫了,看這篇吧 include include include using namespace std define ll long long int n,m,w,v long long f 35 100...
HNOI2007 夢幻島寶珠
題目 題意簡潔明瞭,就是做乙個01揹包,但是揹包的容量 w 非常大,並且給出的物品的體積都能表示成 a times 2 b,a leq 10,b leq 30 顯然這個 a 拿來做揹包的體積非常合適,於是我們按照 b 分類,設 dp 表示只使用 a times 2 i 形式的物品,湊出 j time...
HNOI2007 夢幻島寶珠
題解 一道比較好的題目 首先比較顯然的就是我們要按照a 2 b的b的順序來列舉 那麼狀態f i j 表示當前在b,用了a 2 b 剛開始沒想到怎麼不同層之間搞 看了題解發現非常簡單 由於每一層到最後一層有用的二進位制位至少時從自己的二進位制位開始 所以我們可以捨棄那些沒用的二進位制位 maxa f ...