[HDU 1561] The more, The Better (树形dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561

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

设计状态 dp[u][i] 代表以u为根的,选择i个的最大收获

状态转移 dp[u][j+k] = max( dp[u][j+k], dp[u][j]+dp[v][k] );

注意状态转移的写法

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <cctype>
 7 #include <vector>
 8 #include <map>
 9 #include <set>
10 #include <iterator>
11 #include <functional>
12 #include <cmath>
13 #include <numeric>
14 using namespace std;
15
16 typedef long long LL;
17
18 const int MAX_N = 210;
19 struct EDGE{
20     int to,next;
21 };
22 EDGE edge[MAX_N];
23 int head[MAX_N],ptr;
24
25 void init(){
26     memset(head,-1,sizeof(head));
27     memset(edge,-1,sizeof(edge));
28     ptr = 0;
29 }
30
31 void add_edge(int from,int to){
32     edge[ptr].to = to;
33     edge[ptr].next = head[from];
34     head[from] = ptr++;
35 }
36
37 int N,M;
38 int val[MAX_N],dp[MAX_N][MAX_N],sum[MAX_N];
39 bool vis[MAX_N];
40
41 void dfs(int u){
42     if( vis[u] ) return;
43     vis[u] = true;
44     int tot = 0;
45     sum[u] = 1;
46
47     for(int i=1;i<=M;i++){
48         dp[u][i] = val[u];
49     }
50
51     for(int i=head[u];~i;i=edge[i].next){
52         int v = edge[i].to;
53         if( vis[v] ) continue;
54         tot++;
55         dfs(v);
56         sum[u] += sum[v];
57     }
58
59     if( tot == 0 ){
60         return;
61     }
62
63     for(int i=head[u];~i;i=edge[i].next){
64         int v = edge[i].to;
65 //        printf("v = %d\n",v);
66         int ub = 1;
67         if( u==0 ) ub = 0;
68         for(int j=M;j>=ub;j--){
69             for(int k=1;k<=sum[v];k++){
70                 if( j+k<=M ){
71                     dp[u][j+k] = max(dp[u][j+k],dp[u][j]+dp[v][k]);
72 //                    printf("dp[%d][%d] = dp[%d][%d]+dp[%d][%d]=%d\n",u,j+k,u,j,v,k,dp[u][j]+dp[v][k]);
73                 }
74             }
75         }
76     }
77 }
78
79 int main(){
80     while( scanf("%d%d",&N,&M)!=EOF ){
81         if( N==0&&M==0 ) break;
82         init();
83         memset(val,0,sizeof(val));
84         for(int i=1;i<=N;i++){
85             int t;
86             scanf("%d%d",&t,&val[i]);
87             add_edge(t,i);
88         }
89         memset(dp,0,sizeof(dp));
90         memset(vis,0,sizeof(vis));
91         memset(sum,0,sizeof(sum));
92         dfs(0);
93         printf("%d\n",dp[0][M]);
94     }
95     return 0;
96 }
时间: 2025-01-06 15:19:24

[HDU 1561] The more, The Better (树形dp)的相关文章

hdu 1561 The more, The Better(树形dp+01背包)

The more, The Better Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物.但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡.你能帮ACboy算出要获得

hdu 1561The more, The Better(树形dp&amp;01背包)

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4949    Accepted Submission(s): 2918 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝

HDU 1561The more, The Better(树形DP)

HDU 1561  The more, The Better 题目大意就不说了 直接DP[i][j]表示i为跟节点的子树上攻克j个城堡的所能获得的最多宝物的数量 DP[fa][j] = MAX{DP[fa][i-k] + DP[child][k]}; 首先一个问题就是说如果子树u下的任意子节点被选择了,那么u是一定需要选择的,怎么在DP时保证准确性,其实这个很好解决,我们在计算时是需要枚举k(子节点的攻克数量)的,那么我们迫使k<j就可以了,这样的话DP[fa][j] 就不会被子节点的DP[ch

HDU 4008 Parent and son LCA+树形dp

题意: 给定case数 给定n个点的树,m个询问 下面n-1行给出树边 m个询问 x y 问:以x为根,y子树下 y的最小点标的儿子节点 和子孙节点 思路: 用son[u][0] 表示u的最小儿子 son[u][2] 表示u的次小儿子 son[u][1] 表示u的最小子孙 若lca(x,y)  !=y  则就是上述的答案 若lca(x,y) == y 1.y != 1 那么最小儿子就是除了x外的节点,且此时father[y] 也是y的儿子节点, 而最小的子孙节点就是1 2.y==1 那么特殊处理

HDU 4274 Spy&#39;s Work (树形DP,模拟)

题意: 给定一棵树,每个节点代表一个员工,节点编号小的级别就小,那么点1就是boss了.接下来给出对m个点的限制,有3种符号分别是op=“大于/小于/等于”,表示以第i个点为根的子树所有人的工资之和 大于/小于/等于 x,要求判断m个限制是否冲突了.注意每个员工的工资下限是1,而无上限.ps:可能出现对同个点多个限制,注意取交集. 思路: 很水的题嘛,想复杂了.注意限制是针对整棵子树的!所以我们只需要算出这棵子树的范围,再判断是否和所给的限制有冲突,如果没有冲突的话还得取“所给限制”与“计算出的

hdu 1011 Starship Troopers (依赖背包 树形dp)

题目: 链接:点击打开链接 题意: n个房间组成一棵树,你有m个战队,从1号房间开始依次clear每个房间,在每个房间需要花费的战队个数是bugs/20,得到的价值是the possibility of capturing a brain,求最大的价值. 算法: 树形dp,有依赖的背包问题.(依次clear每个房间) 思路: 状态转移dp[i][j]表示根结点为i时(房间i)花费j个战队能够得到的最大价值(捕捉到一个brain最大的可能值).递归求出每个根结点处的最大值,最后dp[1][m]就是

hdu 4003 Find Metal Mineral 【树形dp,分组背包】

题目:hdu 4003 Find Metal Mineral 题意:火星上发现了一些n个矿厂,有 k 个机器人从 s 点出发采矿,给出路段间的花费cost,求最小的花费采所有的矿. 分类:树形dp + 分组背包 分析:结论1:假如我们从 i点出发k个机器人采完以 k 为根节点的所有矿又回到 i 点,那么花费为 i 为根节点的cost 的和 乘以 k. 对于每个节点,定义状态:dp[i][j] 用 j 个机器人去采以 i 为根节点的子树的所有矿石的最小花费 状态转移方程:dp[father][nu

HDU 1520.Anniversary party 基础的树形dp

Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 12770    Accepted Submission(s): 5142 Problem Description There is going to be a party to celebrate the 80-th Anniversary of the

HDU 6201 2017沈阳网络赛 树形DP或者SPFA最长路

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6201 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过所需要的花费.现在需要你在树上选择两个点,一个作为买入商品的点,一个作为卖出商品的点,当然需要考虑从买入点到卖出点经过边的花费.使得收益最大.允许买入点和卖出点重合,即收益最小值为0. 解法:我们设1为根节点,假设一开始一个人身上的钱为0.我们设dp[i][0]表示从根节点走到i及其子树并中任一点买