NKOJ1469 通向自由的钥匙

P1469通向自由的钥匙

 
时间限制 : 10000 MS   空间限制 : 65536 KB
问题描述

通向自由的钥匙被放n个房间里,这n个房间由n-1条走廊连接。但是每个房间里都有特别 的保护魔法,在它的作用下,我无法通过这个房间,也无法取得其中的钥匙。虽然我可以通过消耗能量来破坏房间里的魔法,但是我的能量是有限的。那么,如果我 最先站在1号房间(1号房间的保护魔法依然是有效的,也就是,如果不耗费能量,我无法通过1号房间,也无法取得房间中的钥匙),如果我拥有的能量为P,我 最多能取得多少钥匙?

输入格式

第一行包含两个非负整数,第一个为N,第二个为P。
接下来n行,按1~n的顺序描述了每个房间。第i+1行包含两个非负整数cost和keys,分别为第i件房取消魔法需要耗费的能量和房间内钥匙的数量。
接下来n-1行,每行两个非负整数x,y,表示x号房间和y号是连通的。

输出格式

一行一个整数,表示取得钥匙的最大值。

样例输入

5 5
1 2
1 1
1 1
2 3
3 4
1 2
1 3
2 4
2 5

样例输出

7

提示

对于20%的测试数据,有n<=20
对于30%的测试数据,有n<=30
对于所有测试数据,有p,n<=100, cost <= 32767, keys<= 32767

 

【题解】

多叉树转二叉树,左儿子右兄弟表示法

各种傻逼错各种卡

 

“将树转化为孩子兄弟表示法,由于根的左孩子还是它的孩子,右孩子是它的兄弟,因此:
树根获取资源,则左右孩子均可获取资源
树根不获取资源,则左孩子不能获取资源,右孩子可获取资源。
设f(i,j)表示以i为根结点的二叉树分配分配j的能量所获得的最多钥匙数,则有

——朱全民

 

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cmath> 
 6 #include <algorithm>
 7 #define min(a, b) ((a) < (b) ? (a) : (b))
 8 #define max(a, b) ((a) > (b) ? (a) : (b))
 9 
10 inline void read(int &x)
11 {
12     x = 0;char ch = getchar(), c = ch;
13     while(ch < '0' || ch > '9')c = ch, ch = getchar();
14     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
15     if(c == '-')x = -x;
16 }
17 
18 const int INF = 0x3f3f3f3f; 
19 const int MAXN = 200 + 10;
20 const int MAXP = 200 + 10;
21 
22 int n,p,dp[MAXN][MAXP],cost[MAXN],key[MAXN];
23 
24 struct Edge
25 {
26     int u,v,next;
27     Edge(int _u, int _v, int _next){u = _u;v = _v;next = _next;}
28     Edge(){}
29 }edge[MAXN];
30 
31 int head[MAXN],cnt;
32 
33 void insert(int a, int b)
34 {
35     edge[++cnt] = Edge(a,b,head[a]);
36     head[a] = cnt;
37 }
38 
39 struct Node
40 {
41     int l, r;
42 }node[MAXN];
43 
44 int b[MAXN];
45 
46 void dfs(int u)
47 {
48     b[u] = 1;
49     int kid1 = 0, kid2 = 0;
50     for(register int pos = head[u];pos;pos = edge[pos].next)
51     {
52         int v = edge[pos].v;
53         if(!b[v])
54         {
55             if(!kid1)
56             { 
57                 kid1 = v;
58                 node[u].l = v;
59             } 
60             else node[kid1].r = v, kid1 = v;
61             dfs(v);
62         }
63     }
64 }
65 
66 int bb[MAXN];
67 
68 void DP(int u)
69 {
70     if(!u)return;
71     bb[u] = 1;
72     if(!bb[node[u].l])DP(node[u].l);
73     if(!bb[node[u].r])DP(node[u].r);
74     for(register int i = 0;i <= p;++ i)
75     {
76         for(register int j = 0;j <= p;++ j)
77             if(i - cost[u] - j >= 0)dp[u][i] = max(dp[node[u].l][j] + key[u] + dp[node[u].r][i - cost[u] - j], dp[u][i]);
78             else dp[u][i] = max(dp[node[u].r][i], dp[u][i]);
79     } 
80 }
81 
82 int main()
83 {
84     read(n), read(p);
85     register int tmp1, tmp2;
86     for(register int i = 1;i <= n;++ i) read(cost[i]), read(key[i]);
87     for(register int i = 1;i < n;++ i)
88     {
89         read(tmp1), read(tmp2);
90         insert(tmp1, tmp2);
91         insert(tmp2, tmp1);
92     }
93     dfs(1);
94     DP(1);
95     printf("%d", dp[1][p]);
96     return 0;
97 }
NKOJ1469 通向自由的钥匙

 

 

 

 

转载于:https://www.cnblogs.com/huibixiaoxing/p/7500391.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值