• 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 通向自由的钥匙
  • 相关阅读:
    Java学习个人备忘录之继承
    Java学习个人备忘录之文档注释
    Java学习个人备忘录之数组工具类
    Java学习个人备忘录之关键字static
    Java学习个人备忘录之构造函数&this
    Java学习个人备忘录之面向对象概念
    Java学习个人备忘录之数组
    Java学习个人备忘录之入门基础
    hdoj1162-Eddy's picture(kruskal)
    hdoj1102-Constructing Roads(Kruskal)
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/7500391.html
Copyright © 2020-2023  润新知