BZOJ1190: [HNOI2007]梦幻岛宝珠【01背包】

1190: [HNOI2007]梦幻岛宝珠

我们对b分层,对于每一层用a背包,然后考虑如何在层之间转移。

F[i]表示还剩余i空间的最优解,略有不同,然后就直接从上一层j转移到j*2+(W这一位是否为1)。

#include<cstdio>
#include<cstring> 
#include<algorithm>
using namespace std;
int n,W,A;long long f[2][1005],Ans;
struct xcw{int a,b,v;bool operator <(const xcw c)const{return b>c.b;};}a[105];
void Work(){
	int now=1,lst=0;f[lst][0]=0;
	for(int i=30,k=1;i>=0;i--,now^=1,lst^=1){
		memset(f[now],192,sizeof(f[now]));
		for(int j=0,x;j<=1000;j++) x=min((j<<1)+((W>>i)&1),1000),f[now][x]=max(f[now][x],f[lst][j]);
		for(;k<=n&&a[k].b==i;k++)
		for(int j=a[k].a;j<=1000;j++) f[now][j-a[k].a]=max(f[now][j-a[k].a],f[now][j]+a[k].v);
	}
	for(int i=0;i<=1000;i++) Ans=max(Ans,f[lst][i]);
}
int main(){
	while(1){
		memset(f,192,sizeof(f));memset(a,0,sizeof(a));Ans=0;
		scanf("%d%d",&n,&W);
		if(n==-1) break;
		for(int i=1;i<=n;i++){
			int w,v;scanf("%d%d",&w,&v);
			while(!(w&1)) a[i].b++,w>>=1;a[i].a=w;a[i].v=v;
			while(a[i].b>30) a[i].a<<=1,a[i].b--;
		}
		sort(a+1,a+1+n);
		Work();
		printf("%lld\n",Ans);
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值