题目大意:HIBiX想买一个很nice的watch,他有一堆coins,HiBix估计这个表的价格不会超过m,所以就打算用硬币拼出在m价格以内的价格数以备付款.来一个"苹果式还债",哈哈... 现在HiBiX问这堆硬币可以堆出多少钱值(在m以内)
思路:用多重背包的装满思想,就是对于每一个V,都尽量的去装.如果装满的就是能够拼出的相应价格,但是有一点有点蒙.看代码最后处....
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define inf -100000000
int n,m;
int dp[100005];
int a[100005],c[1005];
int v;
void ZeroOnePack(int cost,int weight)
{
for(int i=v;i>=cost;i--)
if(dp[i]<dp[i-cost]+weight)
dp[i]=dp[i-cost]+weight;
}
void CompletePack(int cost,int weight)
{
for(int i=cost;i<=v;i++)
if(dp[i]<dp[i-cost]+weight)
dp[i]=dp[i-cost]+weight;
}
void MultiplePack(int cost,int weight,int amount)
{
if(cost*amount>=v)
CompletePack(cost,weight);
else
{
for(int k=1;k<amount;)
{
ZeroOnePack(k*cost,k*weight);
amount-=k;
k<<=1;
}
ZeroOnePack(amount*cost,amount*weight);
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF,n||m)
{
for(int i=0;i<n;i++)
scanf("%d",&a[i]); //硬币面值
for(int i=0;i<n;i++)
scanf("%d",&c[i]); //硬币数量
v=m;
for(int i=1;i<100005;i++)
dp[i]=inf;
dp[0]=0;
for(int i=0;i<n;i++)
MultiplePack(a[i],a[i],c[i]);
int sum=0;
for(int i=1;i<=m;i++)
if(dp[i]==i)//这里还不是很明白为什么这个改为>0也可以AC.囧..
sum++;
printf("%d\n",sum);
}
}