1. 程式人生 > >poj1742(揹包)

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;
	}
}