HDU 2844 Coins(다중 가방)

1418 단어
하나의 다중 가방 문제는 약간 다른 것이 상태 이동 방정식이다. 이곳의 dp는 더 이상 가치와 가치가 아니라 bool값이다. 이것은 dp[i]에서 i의 돈을 모을 수 있는지 없는지를 대표한다. 01가방과 매우 비슷하다. 설명은 다음과 같다.
만약 지금 은화 j를 새로 추가하려고 한다면, 돈을 모을 수 있는지 물어보세요.그렇다면 지금 모은 돈이 필요하다면 i에서 동전 j의 액면가를 뺀 돈은 i-A[j]이다.cost, i-A[j].cost의 돈은 여전히 모을 수 있다면 i도 반드시 모을 수 있다.
  dp[i]=dp[i-A[j].cost]?true:false
그리고 똑같아요.
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int MAX =100005;
bool  dp[MAX];
int v;
int a[MAX],num[MAX];
void zeroOnePack(int cost ,int value)
{
	for(int i=v;i>=cost;i--)
		if(dp[i-cost]==true)
			dp[i]=true;
}
void completePack(int cost,int value)
{
	for(int  i=cost;i<=v;i++)
		if(dp[i-cost]==true)
			dp[i]=true;
}
void multiplePack(int cost,int value,int amount)
{
	if(cost*amount>=v)
	{
		completePack(cost,value);
		return ;
	}
	int k=1;
	while(k<amount)
	{
		zeroOnePack(k*cost,k*value);
		amount-=k;
		k*=2;
	}
	zeroOnePack(amount*cost,amount*value);
}
int main()
{
	int n;
	while(~scanf("%d%d",&n,&v),v,n)
	{
		memset(dp,false,sizeof(dp));
		dp[0]=true;
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		for(int i=1;i<=n;i++)
			scanf("%d",&num[i]);
		for(int i=1;i<=n;i++)
			multiplePack(a[i],1,num[i]);
		int cnt=0;
		for(int i=1;i<=v;i++)
			if(dp[i])
				cnt++;
		printf("%d
",cnt); } return 0; }

좋은 웹페이지 즐겨찾기