HDU 2844 多重背包 二进制压缩

来源:互联网 发布:java语言程序设计 下载 编辑:程序博客网 时间:2024/06/05 04:03
#include<stdio.h> #include<string.h> const int N = 100010; int dp[N];//将钱视为背包的容量 int val[104], num[104], n, V; //V限制的钱 void CompletePack(int val)//完全背包 { for(int i = val; i <= V; i++) dp[i] = dp[i-val] | dp[i]; } void ZeroOnePack(int val) { for(int i = V; i >= val; i--) dp[i] = dp[i] | dp[i-val]; } void MulPack(int val, int num) { if(val *num >= V) //{ CompletePack(val); return ; } int k = 1; while(k < num) //对物品进行二进制压缩{ ZeroOnePack(k * val); num -= k; k <<= 1; } ZeroOnePack(num * val); } int main() { while(scanf("%d%d", &n, &V)) { if(n == 0 && V == 0) break; for(int i = 0; i < n; i++) scanf("%d", &val[i]); for( i = 0; i < n; i++) scanf("%d", &num[i]); memset(dp, 0, sizeof(dp)); dp[0] = 1; for(i = 0; i < n; i++) MulPack(val[i], num[i]); int count = 0; for(i = 1; i <= V; i++) count += dp[i]; printf("%d\n", count); } return 0; }




#include<stdio.h>  #include<string.h>  int w[101],c[101],dp[100100];  int max(int a,int b)  {  return a > b ? a : b;  }  int main()  {  int n,m,num;  int i,j,k;  while(scanf("%d%d",&n,&m) != EOF && (m||n))  {  for(i = 0; i < n; i++)  scanf("%d",w+i);  for(i = 0; i < n; i++)  scanf("%d",c+i);  memset(dp,0,sizeof(dp));  for(i = 0; i < n; i++)  {  if(w[i] * c[i] > m)//完全背包  {  for(j = w[i] ; j <= m; j++)  dp[j] = max(dp[j],dp[j - w[i]] + w[i]);  }  else  {  k = 1;  while( k < c[i])  {  for(j = m; j >= w[i]*k ; j--)//0 1 背包  dp[j] =max(dp[j], dp[j - w[i]*k] + w[i]*k);  c[i] -= k;                  //k个是否放  k <<= 1 ;                 //下一次放的个数为这次的两倍  }  //将剩余的物品全都放入背包  for(j = m; j >= w[i] * c[i] ; j--)  dp[j] = max(dp[j],dp[j-w[i]*c[i]]+w[i]*c[i]);  }  }  num = 0;  for(i = 1 ; i <= m; i++)  if(dp[i] == i)num++;//当dp[i] == i表示价值为i的物品可以购买即背包容量为i的时候“恰好装满”  printf("%d\n",num);  }  return 0;  }