首页 > 其他分享 >树形背包 HDU 1561 The more, The Better

树形背包 HDU 1561 The more, The Better

时间:2023-02-07 17:03:53浏览次数:59  
标签:HDU int 宝物 结点 Better 1561 include head dp


The more, The Better

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3149    Accepted Submission(s): 1857


 

Problem Description

ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗?

 

 

Input

每个测试实例首先包括2个整数,N,M.(1 <= M <= N <= 200);在接下来的N行里,每行包括2个整数,a,b. 在第 i 行,a 代表要攻克第 i 个城堡必须先攻克第 a 个城堡,如果 a = 0 则代表可以直接攻克第 i 个城堡。b 代表第 i 个城堡的宝物数量, b >= 0。当N = 0, M = 0输入结束。

 

 

Output

对于每个测试实例,输出一个整数,代表ACboy攻克M个城堡所获得的最多宝物的数量。

 

 

Sample Input

3 2 0 1 0 2 0 3 7 4 2 2 0 1 0 4 2 1 7 1 7 6 2 2 0 0

 

 

Sample Output

5 13

 

 

Author

8600

 

 

Source

​HDU 2006-12 Programming Contest​

 

 

Recommend

LL

 

 

 

题意就是给定n个点,每个地点有value[i]的宝物,而且有的宝物必须是另一个宝物取了才能取,问取m个点可以获得的最多宝物价值。

一开始感觉很难,细想下不难。

如果是原来n个点,刚好相当于构成深林,取儿子结点必须取父亲结点的关系。我们可以在前面加一个结点构成一颗树。

对于一个根结点,它下面的儿子结点构成子树,每颗子树可以取1,2,3,4····这样个结点。但是只能去一种,其实这就是分组背包了。

分组背包解法见背包九讲。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int N=210;
struct node
{
int v;///终端点
int next;///下一条同样起点的边号
int w;///权值
}edge[N*2];///无向边,2倍
int head[N];///head[u]=i表示以u为起点的所有边中的第一条边是 i号边
int tot; ///总边数
int minn;
void add(int u,int v)
{
edge[tot].v=v;
//edge[tot].w=w;
edge[tot].next=head[u];
head[u]=tot++;
}
int n,m;
int dp[N][N],val[N];
void dfs(int u,int fa)
{
dp[u][1]=val[u];///选一个肯定选自己这个结点
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v= edge[i].v;
///if(fa==v) continue; ///如果下一个相邻节点就是父节点,则证明到底层了,开始递归父节点的兄弟节点
dfs(v,u);
for(int j=m;j>0;j--) ///背包容量
///下面这个循环必须是k<j结束,不能取等号,因为至少需要留一个点来取u点
for(int k=1;k<j;k++) ///选择用户
{
dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
}
}

}
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0) break;
memset(head,-1,sizeof(head));
memset(dp,0,sizeof(dp));
tot=0;

for(int i=1;i<=n;i++)
{
int w,v;
scanf("%d%d",&v,&w);
add(v,i);
val[i]=w;
}
//dp[0][1]=0;
m++;
val[0]=0;///虚拟构造了结点0
dfs(0,-1);
printf("%d\n",dp[0][m]);
}

return 0;
}

 

标签:HDU,int,宝物,结点,Better,1561,include,head,dp
From: https://blog.51cto.com/u_14932227/6042471

相关文章