P3188 HNOI2007 夢幻島寶珠

2022-05-19 08:34:46 字數 1425 閱讀 9176

傳送門

注意到 $a,b$ 不大

考慮對每乙個 $a*2^b$ 的 $b$ 分別揹包

設 $f[i][j]$ 表示只考慮 $b=i$ 的物品時,容量為 $j= \sum a$ 的最大價值

這個就是普通的 $01$ 揹包

考慮把 $f[i][j]$ 之間合併起來,為了得到容量為 $w$ 時的答案,我們要把 $f$ 的含義稍微變化一下

變成 $f[i][j]$ 表示當前考慮了 $b=2^1$ 到 $b=2^i$ 時的物品,容量為 $j*2^i$ 加上 $w$ 二進位制下前 $i-1$ 位的值,此時的最大價值

考慮用 $f[i-1]$ 更新 $f[i][j]$,列舉總體積為 $(j-k)*2^i$ 的 $b=2^i$ 的物品的最大價值($f[i][j-k]$)

加上總體積為 $2k*2^$ 的 $b<2^i$ 的物品的最大價值 ($f[i-1][k*2]$),注意我們還要考慮 $w$ 的容積,所以設 $w$ 第 $i-1$ 位為 $p$

那麼轉移為 $f[i][j]=f[i][j-k]+f[i-1][ min(sw[i-1],k*2+p) ]$,此時 $sw[i]$ 表示第 $b<=2^i$ 時物品的體積和上取整為 $2^$

注意上面列舉 $j$ 的時候要從大到小列舉

轉移的細節挺多的...,最終答案即為 $f[m][1]$, $m$ 表示 $w$ 的最高位

#include#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;inline

intread()

while(ch>='

0'&&ch<='

9')

return x*f;

}const

int n=107,m=1007

;int n,w,m,sw[37

];struct

orb;

vector

v[37

];ll f[

37][m];

intmain()

); sw[cnt]+=w;

}int t=1,cnt=0; while(t<=w) t<<=1,cnt++;

m=cnt-1

;

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

//f[i][j]=f[i][j-k]+f[i-1][ (k<<1) | ( (w>>(i-1)) &1) ]

for(int i=1;i<=m;i++)

printf(

"%lld\n

",f[m][1

]); }

return0;

}

洛谷 P3188 HNOI2007 夢幻島寶珠

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

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

洛谷 P3188 HNOI2007 夢幻島寶珠

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