首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

hdu 1561 委以背包

2012-08-07 
hdu 1561 依赖背包题意:n座城堡,每个里面都有宝物,要求在你可以攻占m个城堡得到的最多的宝物,但是如果要攻

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 205struct 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);    }}


热点排行