多重背包-hdu2191,完全背包-hdu4508,二维费用背包hdu2159

/*

多重背包,用2进制的拆分思想,转化为01背包

*/

#include<cstdio>

#include<cstring>

#define maxn 99999

#define max(a,b) (a)>(b)?(a):(b)

int dp[maxn],c[maxn],v[maxn];

int main()

{

	int Z,V,m,i,a,b,x,j;

	scanf("%d",&Z);

	while(Z--)

	{

		scanf("%d%d",&V,&m);

		int cnt=1;

		for(i=1;i<=m;i++)

		{

			scanf("%d%d%d",&a,&b,&x);

			int t=1;

			while(x>=t)

			{

				v[cnt]=a*t;

				c[cnt++]=b*t;

				x-=t;

				t<<1;

			}

			if(x)

			{

				v[cnt]=a*x;

				c[cnt++]=b*x;

			}

		}

		memset(dp,0,sizeof(dp));

		for(i=1;i<cnt;i++)

			for(j=V;j>=v[i];j--)

				dp[j]=max(dp[j],dp[j-v[i]]+c[i]);

		printf("%d\n",dp[V]);

	}

	return 0;

}



 

/*

完全背包

转化为可重复的01背包

*/

#include<cstdio>

#include<cstring>

#define max(a,b) (a)>(b)?(a):(b)

#define maxn 100010

int dp[100010];

int main()

{

	int n,i,j,V;

	int c[200],v[200];

	while(scanf("%d",&n)!=EOF)

	{

		memset(dp,0,sizeof(dp));

		for(i=1;i<=n;i++)

			scanf("%d%d",&c[i],&v[i]);

		scanf("%d",&V);

		for(i=1;i<=n;i++)

			for(j=v[i];j<=V;j++)

				dp[j]=max(dp[j],dp[j-v[i]]+c[i]);

		printf("%d\n",dp[V]);

	}

	return 0;

}

 

/*

二维费用背包

变形较多。三重循环较难掌握。

*/

#include<cstdio>

#include<cstring>

#define maxn 150

#define max(a,b) (a)>(b)?(a):(b)

int main()

{

	int c[maxn],v[maxn],dp[maxn][maxn];

	int ex,pa,ki,mm,i,j,k;

	while(scanf("%d%d%d%d",&ex,&pa,&ki,&mm)!=EOF)//experience,patience,kinds,mostmonserts

	{

		int f=1;

		memset(dp,0,sizeof(dp));

		for(i=1;i<=ki;i++)

			scanf("%d%d",&c[i],&v[i]);

		for(i=1;i<=ki;i++)

			for(j=v[i];j<=pa;j++)

				for(k=1;k<=mm;k++)

					dp[j][k]=max(dp[j][k],dp[j-v[i]][k-1]+c[i]);

		for(i=1;i<=pa;i++)

			for(k=1;k<=mm;k++)

				if(dp[i][k]>=ex)

				{

					f=0;

					printf("%d\n",pa-i);

					goto A;

				}

		if(f)

			printf("-1\n");

		A:;

	}

	return 0;

}


 

 

你可能感兴趣的:(HDU)