hdu 3449 Consumer(DP)

点击打开链接

题目;依赖背包。。

购物,买相应物品时,必须先买其对应的箱子。。以及n个盒子的价钱和,该盒子中所可以装的物品的价格和价值。

求最大价值!!

一般的:

dp[i][j]=dp[i][j-cost[i]]+value[i];

但需要考虑盒子的价值。故

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

其中dp[i][j]表示使用前i个盒子,花费j所得到的最大价值;考虑第i个盒子到底选不选以及选的话,该多花多少钱,很明显时间复杂度高,故优化;

仔细分析会发现dp[i-1][j-k]+pack[i][k]是在考虑第i个盒子的情况下的最大价值;

将盒子的价值当做0,在金钱j下,首先将盒子的价钱考虑进去,那么剩下的只是挑选盒子中的物品,即01背包;

令f(i,j)为前i个盒子且第i个一定考虑在内的情况下的最大价值,所以初始化为f(i,j)=max(f[i][j-box[i]]+0)(PS:初始化后,盒子的影响就没有了);之后01就可以了!

#include"stdio.h"
#include"string.h"
#define max(x,y) x>y?x:y;
int dp1[100001];
int dp2[100001];
int main()
{
	int n,w,i,j,k;
	int cost[55][11],value[55][11];
	int num[55],box[55];
	while(scanf("%d%d",&n,&w)!=-1)
	{
		for(i=1;i<=n;i++)
		{
			scanf("%d",&box[i]);
			scanf("%d",&num[i]);
			for(j=1;j<=num[i];j++)
				scanf("%d%d",&cost[i][j],&value[i][j]);
		}
		memset(dp1,0,sizeof(dp1));
		for(i=1;i<=n;i++)
		{
			for(j=w;j>=box[i];j--)
				dp2[j]=dp1[j-box[i]];//初始化,消除盒子的影响!!
			for(j=1;j<=num[i];j++)
			{
				for(k=w;k>=cost[i][j]+box[i];k--)
					dp2[k]=max(dp2[k],dp2[k-cost[i][j]]+value[i][j]);
			}
			for(j=w;j>=box[i];j--)
				dp1[j]=max(dp1[j],dp2[j]);//更新dp1
		}
		printf("%d\n",dp1[w]);
	}
	return 0;
}
	


原文地址:https://www.cnblogs.com/yyf573462811/p/6365145.html