POJ1274(多重背包)

来源:互联网 发布:蜜丝佛陀知乎 编辑:程序博客网 时间:2024/06/05 22:41

二进制拆分。

将一个数n拆成1,2,4,……2^(k-1),n-(2^k-1),其中k是n的二进制中1的最高位的位置。

比如6可以表示成1,2,3;4可以表示成1,2,1。

这样数0..n就可以表示为a0*1+a1*2+a2*4+……+ak-1*2^(k-1)+ak*(n-(2^k-1))。其中ai可以取0或者1。

#include <iostream>#include <vector>#include <algorithm>#include <cstdio>#include <cstring>using namespace std;int main(){int cash,n;int i,j;int w[150];int dp[100005];while (scanf("%d",&cash)!=EOF){memset(w,0,sizeof(w));memset(dp,0,sizeof(dp));int counter=0;scanf("%d",&n);for (i=0;i<n;i++){int a,b;scanf("%d%d",&a,&b);int temp=a;for (j=0;(a>>1)!=0;j++){w[counter++]=b*(1<<j);a>>=1;}w[counter++]=b*(temp-(1<<j)+1);}for (i=0;i<counter;i++)for (j=cash;j>=1;j--)if (j-w[i]>=0 && dp[j-w[i]]+w[i]>dp[j])dp[j]=dp[j-w[i]]+w[i];printf("%d\n",dp[cash]);}}


0 0