一个背包,当然正解是完全背包,不过我用拆分法水过了。。
小于等于7的数可由1 2 4拼成
小于等于15的数可有1 2 4 8拼成
那么对于7到15之间的数n
可有1 2 4 n-7拼成
运用这个思想把有限制的背包转化成0/1背包就好了。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
bool isv[100020];
int a[120], c[120], allv[2200];
int tot;
int n, m;
int ans;
int main()
{
while (scanf("%d%d", &n, &m))
{
if (n == 0 && m == 0)break;
tot = 0; ans = 0;
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
for (int i = 0; i < n; i++)
{
scanf("%d", &c[i]);
}
for (int i = 0; i < n; i++)
{
int temp = 0;
int q = 1;
allv[tot++] = a[i];
temp += q;
while ((temp+q*2) < c[i])
{
q *= 2;
allv[tot++] = a[i] * q;
temp += q;
}
if ((c[i] - temp) > 0)
allv[tot++] = (c[i] - temp)*a[i];
}
isv[0] = 1;
for (int i = 0; i < tot; i++)
{
for (int j = m; j >= allv[i]; j--)
{
isv[j] = (isv[j - allv[i]] | isv[j]);
}
}
for (int i = m; i >= 1; i--)
{
if (isv[i])
ans++;
}
printf("%d\n", ans);
for (int i = 0; i <= m; i++)
isv[i] = 0;
}
}