假设每个硬币的重量为A[i],数量是C[i] 价格是A[i]
定义dp(i, j)为前i件物品装在容量为j的背包中能够取得的最大价值
我们只需要求出dp(n, m)
因为在求出dp(n, m)的过程中,dp(n, 1) ,dp(n, 2)......dp(n, m - 1)都已经求出来了
我们就可以看dp(n, i)是否等于i来判断能否用硬币买价格为i的物品
#include <queue>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define MAX_N 100005
#define INF 0x3f3f3f
using namespace std;
typedef long long int ll;
int dp[MAX_N];
int main()
{
//freopen("1.txt", "r", stdin);
int weight[MAX_N], value[MAX_N], num[MAX_N];
int n, m;
while (cin >> n >> m && n && m)
{
for (int i = 1; i <= n; i++)
{
scanf("%d", &weight[i]);
value[i] = weight[i];
}
for (int i = 1; i <= n; i++)
scanf("%d", &num[i]);
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
{
if (weight[i] * num[i] >= m)
{
for (int j = weight[i]; j <= m; j++)
{
if (dp[j] < dp[j - weight[i]] + value[i])
dp[j] = dp[j - weight[i]] + value[i];
}
}
else
{
int k = 1;
while (k < num[i])
{
for (int j = m; j >= k * weight[i]; j--)
{
if (dp[j] < dp[j - k * weight[i]] + k * value[i])
dp[j] = dp[j - k * weight[i]] + k * value[i];
}
num[i] -= k;
k <<= 1;
}
for (int j = m; j >= num[i] * weight[i]; j--)
{
if (dp[j] < dp[j - num[i] * weight[i]] + num[i] * value[i])
dp[j] = dp[j - num[i] * weight[i]] + num[i] * value[i];
}
}
}
int ans = 0;
for (int i = 1; i <= m; i++)
{
if (dp[i] == i)
ans++;
}
printf("%d\n", ans);
}
return 0;
}