HDU 3593 The most powerful force 树形DP(背包)

来源:互联网 发布:做歌软件 编辑:程序博客网 时间:2024/05/22 00:26

原题:

The most powerful force

Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 938    Accepted Submission(s): 238


Problem Description
The leaders of AC country made a decision to regain the TW Island. But they have to face the powerful force from USB. So the leaders have to hire some excellent soldiers from the training base called ALPC to format the most powerful force.
The followings are the consists of ALPC:
1.  There are more than one alpcs who are generals, like alpc04.
2.  Every alpc has a direct superior, except the generals.
3.  The alpc who has underling is an officer (Every officer’ number is no more than 500, like alpc21, alpc32).
4.  If send one alpc to the war, so will his direct superior. Of course the general’s direct superior is himself.
5.  Every alpc has two values. Vi is the fighting strength and Ci is the cost that the leader have to pay for the soldier.

Due to the AC country has limited financial resources, the leaders want to format the most powerful force with the cost not exceed G. Obviously, it is an uphill task! Therefore, the leaders of the AC country have assigned the task to alpc72 because of the outstanding behavior he had done at the ACM/ICPC. But alpc72 has been lost in hunting PLMM nowadays, so that he has no time to deal with this problem. What’s more, he left it to you.
 

Input
There will have several test cases. 
The first line has two integers N and G, which stand for the total number of soldiers and the maximum cost. Soldiers numbered consequently from 1 to N. (1<=N<=100000, 1<=G<=10000)
The next N lines, each has three integers Ci, Vi and Fi. They are the cost, the measure of power and the direct superior of the ith soldier. (0<=Ci<=1000000, 0<=Vi<=1000000)
 

Output
Output one integer (must within 32 bits)as the maximum fighting strength of the most powerful force.
 

Sample Input
5 101 2 110 5 21 1 1 1 1 11 1 35 101 2 12 4 21 1 1 1 1 11 1 3
 

Sample Output
59
 
Source
2010 ACM-ICPC Multi-University Training Contest(16)——Host by NUDT
 


题意+题解:

树形背包,树上的结点有权值和花费,在花费上限为G的情况下求最大权值。其中选择了一个结点,那么这个结点的祖先都要被选。

当时想到树形分组背包了,但是自己写的时候又写不出来,看了背包9讲里对于泛化物品的讲解,稍微懂了些原理,写的时候是照着暑假集训的时候一道树形分组背包的题写的,但是按照n^2的泛化物品合并的时候又给T掉了,潘少给讲了一种非常巧妙的优化,减少了一维,泛化物品合并通过一个讲父亲节点的dp值直接复制给儿子结点的方法就给压缩了一维。太过于难想了。。。。。。膜拜之。。。

状态:dp[i][j] 表示以第i个结点为根的子树中,给其一个j的容量,能获得的最大权值

虽然点非常的多,但是非叶子结点只有500个(而且是前500.....)所以在dfs的时候对于儿子是叶子结点的时候可以直接按照01背包算,这个在背包9讲中也有讲述

dfs(u.v)就是求dp[u][v]的值

具体看代码把,我在里面有比较详细的注释,用的就是对泛化物品的合并操作



//大二寒假集训:第一章:D_The most powerful force#include<cstdio>#include<cstring>#include<vector>#include<algorithm>using namespace std;int dp[505][10005];int n,g;vector <int >T[100010];//int index[505],anti_index[100010];int cost[100010],value[100010];int find_max(int a,int b){return a>b?a:b;}void dfs(int u,int volume){int son,i,j,v,s,k,grandson;k=T[u].size();//if(anti_index[u]!=-1)v=anti_index[u];for ( i = 0; i < k; i++){son=T[u][i];if (T[son].empty())//叶子结点,用01背包更新根节点,这里不用管他的兄弟是否是非叶子结点,遇到一个更新一个就行{for ( j = volume; j >=cost[son] ; j--){dp[u][j]=max(dp[u][j],dp[u][j-cost[son]]+value[son]);}}else//儿子结点也是非叶子节点,用泛化物品求和方法更新根节点{//s=anti_index[son];for ( j = 0; j <=volume-cost[son] ; j++)//这一步非常关键,是优化复杂度的一个重要步骤,直接把根的dp值赋给儿子{//这样再用孙子结点更新儿子结点时其实就是更新根节点,这样就用一维就把根节点由两个泛化背包的和球出来了,不然要二维dp[son][j]=dp[u][j];}//这里不需要遍历孙子结点,因为更新儿子结点的步骤是递归在儿子的循环里做的if(volume-cost[son]>0)dfs(son,volume-cost[son]);//给儿子结点时,根节点必选,先扣除其花费for ( j = volume; j >=cost[son] ; j--){dp[u][j]=max(dp[u][j],dp[son][j-cost[son]]+value[son]);}}}}int main(){int i,temp,parent;cost[0]=0;value[0]=0;while (scanf("%d%d",&n,&g)!=EOF){//memset(anti_index,-1,sizeof(anti_index));memset(dp,0,sizeof(dp));//index[0]=0;anti_index[0]=0;for ( i = 1; i <=n ; i++){scanf("%d%d%d",&cost[i],&value[i],&parent);if(parent==i)T[0].push_back(i);//index[++k]=i;anti_index[i]=k;//表明这是一个非叶子结点,存储标号与dp相对应else T[parent].push_back(i);}dfs(0,g);printf("%d\n",dp[0][g]);for ( i = 0; i <=n ; i++)T[i].clear();}return 0;}


0 0
原创粉丝点击