hdu 1561 委以背包

hdu 1561 依赖背包

题意:n座城堡,每个里面都有宝物,要求在你可以攻占m个城堡得到的最多的宝物,但是如果要攻破一个城堡,必须要攻破它依赖的那个城堡,例如,如果a依赖b,那么如果想要攻破a就必须先攻破b。把每个城堡看作是物品,那么这个物品的城堡数量是1,价值就是宝物了。

解题思路:根据题意知道这种关系会形成一颗多叉树,根节点是0.从P=0开始,

1、遍历所有P的孩子,遇到某个孩子还有孩子,就把该节点当作P,继续1,直到遍历完所有的节点,如果P的所有孩子都没有孩子,那么转到2,存在有的孩子有孩子,转到3;

2、对P的所有孩子进行01背包,假设P的价值是Vp,P共有n个孩子,然后对每个孩子进行01背包(因为对于每个城堡只能取一次),那么可以得到城堡数量从0到n对应的最大价值(0对应的肯定是0了),用dp[i]表示,i代表城堡数量,dp[i]代表价值,接着从i=0开始,都加上P的价值Vp(因为所有的物品都依赖P),同时城堡的个数也加1;最后把得到的n+1个物品保存到P点,这样,这些物品就相当于分组背包里面的一组背包了,储存在castle里面,然后接着步骤1的遍历;

3、这个就很简单了,由于已经遍历过P所有孩子了,所以,只需要再从头开始遍历一遍所有孩子,如果遍历的孩子还有孩子,那么就把它的所有孩子当作是分组背包处理,如果遍历的孩子没有孩子,那么就当01背包处理,最后会得到一个城堡数量从0到m(也就是题目给的城堡数量的上限,以为不确定P的所有孩子的个数,所以就用最大的m)对应的最大价值,这个时候,如果P是0,那么就输出dp[m]就好了,如果不是,像2一样,dp[i]代表的价值都加上P的价值,数量也加1,也储存在castle里面,继续步骤1的遍历;

具体代码如下:

(提示:结构体s[i]代表城堡i的信息:num表示城堡的数量,value代表价值,key是自身的序号,depend代表i依赖的城堡编号;list castle[i]记录依赖i的城堡的信息)

#include <cstdio>
#include <string.h>
#include <iostream>
#include <list>

using namespace std;
#define N 205
struct ss{
    int num,value,key,depend;//物品的个数,价值,自身的序号,依赖的序号;
}s[N],one;
list <ss> castle[N];
int dp[N],m;
void fun(int n)
{
	int num=0,i,j,k,minn;
	list <ss>::iterator p,q;
	p=castle[n].begin();
	while(p!=castle[n].end())
	{
		if(castle[(*p).key].size()!=0)
			fun((*p).key);
		p++;
	}	
	memset(dp,0,sizeof(dp));
	p=castle[n].begin();
	while(p!=castle[n].end())
	{
		if(castle[(*p).key].size()!=0)
		{			
			for(i=m;i>=0;i--)
			{
				q=castle[(*p).key].begin();
				while(q!=castle[(*p).key].end())
				{
					if(i-(*q).num>=0)
					dp[i]=max(dp[i],dp[i-(*q).num]+(*q).value);
					q++;
				}
			}
		}
		else
		{
			for(i=m;i>=(*p).num;i--)
				dp[i]=max(dp[i],dp[i-(*p).num]+(*p).value);
		}
		p++;
	}
	
	castle[n].clear();
	if(!n)
		cout<<dp[m]<<endl;
	else
	{
		one.depend=n;one.key=n;
		for(i=m;;i--)
		{
			if(dp[i])
			{
				one.num=i+1;one.value=dp[i]+s[n].value;
				castle[n].push_back(one);
			}
			else
			{
				one.num=1;one.value=s[n].value;
				castle[n].push_back(one);
				break;
			}
		}
	}
	
}

int main()
{
    int n;
    while(cin>>n>>m)
    {
		if(!n&&!m)
			return 0;
        int i,j,k,x;
        for(i=0;i<=n;i++)
			castle[i].clear();
		for(i=0;i<n;i++)
		{
			scanf("%d%d",&s[i+1].depend,&s[i+1].value);
			s[i+1].num=1;	s[i+1].key=i+1;
			castle[s[i+1].depend].push_back(s[i+1]);
		}
		fun(0);	
    }
}