hdu-3033 又见0-1背包

这个是稍微复杂的0-1背包,或者可以说是二维背包的变形。总之,就是一个特殊背包,特殊在哪呢?稍后分析

题意:

某人要买鞋,有k个品牌,每个品牌有j个款,每款都有标价和价值,要求已经M元内,每个品牌至少买一双鞋的最大价值和。

分析:

难点1 每个品牌至少一双,很令人纠结呀。

其实的其实,可以这样想,k个品牌,可以直接理解为重量为k,只要k全部填满,即为k个品牌至少一个。

理解了这个就不难知道,DP[i][j]代表,第i个品牌,资金数为j的最大价值和。

难点2 状态转移方程 这个比较费神,怎么个转移法呀,子状态是什么呢。

可以这样想,当前在放置第i个品牌的第j个物品,那么有四种状态

a,,第i个品牌未放置过,第j个物品不放置DP[i-1][w];//值不变

b,第i个品牌未放置过,第j个物品要放置DP[i-1][w-N[i][j].b];

c,第i个品牌已放置过,第j个物品也放置DP[i][w-N[i][j].b];

d,第i个品牌已放置过,第j个物品不放置DP[i][w]。//值不变

好吧 看似很难得题分析完  也就很好理解了、、、、不枉费苦思冥想几天呀

写题中看到一篇文章,讲解的也很不错,留个链接、、谢谢博主,(*^__^*) 嘻嘻……

代码:


#include <iostream>
#include<algorithm>
using namespace std;
#define INF 999999
#define max(a,b) (((a)>(b))?(a):(b))
int sum[11];//每种品牌的商品数量
struct info
{
	int b;//标价
	int v;//价值
}N[11][101];//每种品牌的每双鞋的信息
int DP[11][10001];//i个品牌,j资金的最大价值
int main()
{
	int n,m,k,i,j,w;
	while(cin>>n>>m>>k)//n个鞋款,m总金额,k种品牌
	{
		memset(sum,0,sizeof(sum));
		int p;
		for(i=0;i<n;i++)
		{
			cin>>p;
			sum[p]++;
			cin>>N[p][sum[p]].b>>N[p][sum[p]].v;//都是从1开始				
		}
		//初始化(必须填满)
		for(i=0;i<=k;i++)
			for(j=1;j<=m;j++)
				DP[i][j]=-INF;
		for(j=1;j<=m;j++)
			DP[0][j]=0;
		for(i=1;i<=k;i++)//品牌
		{
			for(j=1;j<=sum[i];j++)//第几双鞋
			{
				for(w=m;w>=1;w--)//钱
				{
					if(w>=N[i][j].b)
					{
						if(DP[i][w-N[i][j].b]!=-INF)//放过i,放j
							DP[i][w]=max(DP[i][w],DP[i][w-N[i][j].b]+N[i][j].v);
						if(DP[i-1][w-N[i][j].b]!=-INF)//未放i,放j
							DP[i][w]=max(DP[i][w],DP[i-1][w-N[i][j].b]+N[i][j].v);
					}
				}
			}
		}
		if(DP[k][m]==-INF) cout<<"Impossible"<<endl;
		else cout<<DP[k][m]<<endl;
	}
	return 0;
}

你可能感兴趣的:(hdu-3033 又见0-1背包)