二进制优化就是:本来你要选24个这种物品,我可以把他拆成1,2,4,8和9,9是由24-1-2-4-8得来的。任意一个实数都可以这样拆开。
为什么要优化呢,因为快啊。
#include<bits/stdc++.h>
using namespace std;
#define INF -0x3f3f3f3f
int value[100005],dp[100005],num[100005],n,m;
void ZeroOnePack(int cost,int weight)
{
for(int i=m;i>=cost;i--)
{
dp[i]=max(dp[i],dp[i-cost]+weight);
}
}
void CompletePack(int cost,int weight)
{
for(int i=cost;i<=m;i++)
{
dp[i]=max(dp[i],dp[i-cost]+weight);
}
}
void MultiplePack(int cost,int weight,int amount)
{
if(cost*amount>=m)CompletePack(cost,weight);
else
{
int k=1;
while(k<amount)
{
ZeroOnePack(k*cost,k*weight);
amount-=k;
k<<=1;
}
ZeroOnePack(amount*cost,amount*weight);
}
}
int main()
{
while(scanf("%d%d", &n, &m), n || m){
memset(value,0,sizeof(value));
memset(num,0,sizeof(num));
for (int i = 1; i <= m; i++)
dp[i] = INF;
dp[0] = 0;
int maxn = 0;
for (int i = 0; i < n; i++)
scanf("%d", &value[i]);
for (int i = 0; i < n; i++){
scanf("%d", &num[i]);
maxn += value[i] * num[i];
}
m = min(maxn, m);//背包容量取预计最大金额和所有硬币最大金额的最小值 不然二进制可能会多算一位
for (int i = 0; i < n; i++){
MultiplePack(value[i], value[i], num[i]);
}
int ans = 0;
for (int i = 0; i <= m ; i++)
if(dp[i] > 0) ++ans;
printf("%d\n", ans);
}
return 0;
}