poj1742(背包)

一个背包,当然正解是完全背包,不过我用拆分法水过了。。

小于等于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;
	}
}

猜你喜欢

转载自blog.csdn.net/guoshiyuan484/article/details/82495905