poj1276

来源:互联网 发布:2017网络红歌都有什么 编辑:程序博客网 时间:2024/05/17 08:18


多重背包问题,转化为二进制后,变为01背包问题。

转化方法,

假设当前某种物品有n件,那么将n件该类物品变为 1个该物品,2个该物品,4个该物品,直至2^k个该物品,2^(k+1)-1<=n这时我们发现,只要是数量少于2^(k+1)次方的该物品,都在背包dp中更新过了,那么在加上n-(2^(k+1)-1)之后,该物品的多重背包的所有情况就都被考虑过了。



据说单调队列能做到n,,,正在学习中

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>#include<set>#include<queue>bool flag[200100];using namespace std;int main(){int i,j,k,sum,worth,v,n;while (scanf("%d",&v)!=EOF){memset(flag,0,sizeof(flag));flag[0]=true;scanf("%d",&n);for (i=1;i<=n;i++){scanf("%d%d",&sum,&worth);for (j=1;((j<<1)-1)<=sum;j=j<<1)for (k=v;k>=j*worth;k--)if (flag[k-j*worth]==true)flag[k]=true;j=sum-(j-1);for (k=v;k>=j*worth;k--)if (flag[k-j*worth]==true)flag[k]=true;}for (k=v;k>=0;k--)if (flag[k]){printf("%d\n",k);break;}}return 0;}


0 0