卧薪尝胆,厚积薄发。
HNOI2007 梦幻岛宝珠
Date: Fri Oct 19 17:28:55 CST 2018
In Category:
NoCategory
Description:
$N$
个物品,每个物品都有重量和价值。选一些物品总重量不超过
$W$
且总价值最大。
$N\leqslant100,W\leqslant2^{30},$
并且保证每个物品的重量符合
$a\times2^b$
。
Solution:
既然告诉
$w[i]=a\times2^b$
那就按二进制位考虑,设
$f_1[i][j]$
表示只考虑
$b=i$
的物品
$a$
的和为
$j$
所能获得的最大价值,这个可以把物品按
$b$
分组然后每组做
$01$
背包,再设
$f_2[i][j]$
表示所有
$b<i$
的物品都已考虑完,都合并到
$i$
这一位上需要的容积为
$j\times 2^i$
能获得的最大价值,转移时发现
$f_2[i-1][j]$
等价于
$f_2[i][\lceil\frac{j-(m的第i位是1)}2\rceil]$
,可以把每个
$f_2[i][j]$
都像这样提高一位,看成一个物品,然后在
$f_1[i][j]$
的基础上再做一个类似分组背包的东西,因为只能选一个
$f_2$
,否则会选重,但是由于有重量为
$0$
的物品存在所以需要用一个
$g[i]$
辅助转移。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<vector>
#include<cctype>
#include<cstring>
using namespace std;
int n,m;
#define R register
inline int rd()
{
R int res = 0,f = 1;
R char c = getchar();
while(!isdigit(c))
{
if(c == '-')f = -1;
c = getchar();
}
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res * f;
}
#define MAXN 110
int w[MAXN],v[MAXN];
struct item{int w,v;};
vector<item> s[32];
#define MAX 1000
int f[32][MAX + 10];
int g[MAX + 10];
int main()
{
while(scanf("%d%d",&n,&m) && n != -1 && m != -1)
{
for(R int i = 0;i <= 31;++i)s[i].clear();
for(R int i = 1;i <= n;++i)
{
w[i] = rd();v[i] = rd();
}
for(R int i = 1;i <= n;++i)
{
R int cnt = 0;
while(w[i] % 2 == 0)
{
++cnt;
w[i] /= 2;
}
s[cnt].push_back((item){w[i],v[i]});
}
memset(f,0xc0,sizeof(f));
for(R int i = 0;i <= 31;++i)
{
f[i][0] = 0;
for(R vector<item>::iterator it = s[i].begin();it != s[i].end();++it)
{
for(R int j = MAX;j >= it -> w;--j)
{
f[i][j] = max(f[i][j],f[i][j - it -> w] + it -> v);
}
}
}
for(R int i = 0;i <= 30;++i)
{
memset(g,0xc0,sizeof(g));
for(R int k = MAX;k >= 0;--k)
{
for(R int j = 0;j <= MAX;++j)
{
R int vi = (j - ((m >> i) & 1) + 1) / 2;
if(k >= vi)g[k] = max(g[k],f[i + 1][k - vi] + f[i][j]);
else break;
}
}
for(R int k = MAX;k >= 0;--k)f[i + 1][k] = g[k];
}
cout << f[31][0] << endl;
}
return 0;
}
In tag:
DP-背包
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡