shjwudp

导航

 

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

题意:一个树上的塔防游戏。给你n个结点的树,你要在树结点上建塔防御,在第 i 个结点上有 ki 种防御塔可供选择,每个塔给你建塔花费 pricei 和塔能造成的伤害 poweri (可以认为每个塔只能攻击一次),现在有一个怪物从结点1出发,随意的沿着树边去叶子结点,问你最坏的情况最大能对怪物造成多少伤害(即假设怪物会沿着受伤最小的路径走),开始有 m 单位钱

2<=n<=1000, 0<=ki<=50, 0<=pricei<=200, 0<=poweri<=5e4, 0<=m<=200

题解:树形dp,f[u][x]表示在以 u 为根的子树上花费 x 最多造成 f[u][x] 的伤害

考虑状态转移,对于当前结点u他有儿子 v1,v2,,,,vt,你现在有 x 单位钱,如何给这 t 个儿子分配使得伤害最小的儿子伤害最高?

依次遍历儿子,用maxSon[y]表示给到当前儿子为止总共花 y 单位钱,获得的最大收益

时间复杂度:O(n*m^2)

  1 /*
  2  * Problem:  
  3  * Author:  SHJWUDP
  4  * Created Time:  2015/10/6 星期二 22:57:51
  5  * File Name: 1001.cpp
  6  * State: 
  7  * Memo: 
  8  */
  9 #include <iostream>
 10 #include <cstdio>
 11 #include <vector>
 12 #include <cstring>
 13 #include <algorithm>
 14 
 15 using namespace std;
 16 
 17 const int INF=0x7f7f7f7f;
 18 
 19 struct Graph {
 20     struct Edge {
 21         int u, v;
 22     };
 23     int n, m;
 24     vector<Edge> edges;
 25     vector<vector<int>> G;
 26     vector<vector<pair<int,int>>> tower;
 27     vector<vector<int>> f;
 28     Graph(int _n):n(_n),m(0),G(_n),tower(n),f(n){}
 29     void addEdge(int u, int v) {
 30         edges.push_back({u, v});
 31         m=edges.size();
 32         G[u].push_back(m-1);
 33     }
 34     vector<int> & operator[](int x) {
 35         return G[x];
 36     }
 37 };
 38 
 39 int n, m;
 40 void dfs(Graph & G, int u, int fa) {
 41     auto & tower=G.tower[u];
 42     auto & bag=G.f[u];
 43     bag.assign(m+1, 0);
 44     for(const auto & p : tower) {
 45         if(p.first>m) continue;
 46         bag[p.first]=max(bag[p.first], p.second);
 47     }
 48     if(G[u].size()==1 && u!=0) return;
 49     vector<int> maxSon(m+1, INF);
 50     for(auto i : G[u]) {
 51         const auto & e=G.edges[i];
 52         if(e.v==fa) continue;
 53         dfs(G, e.v, u);
 54         const auto & vbag=G.f[e.v];
 55         for(int j=m; j>=0; --j) {
 56             int mx=0;
 57             for(int k=0; k<=j; ++k) {
 58                 mx=max(mx, min(maxSon[j-k], vbag[k]));
 59             }
 60             maxSon[j]=mx;
 61         }
 62     }
 63     for(int v=m; v>=0; --v) {
 64         for(int i=0; i<=v; ++i) {
 65             if(maxSon[i]==INF) continue;
 66             bag[v]=max(bag[v], bag[v-i]+maxSon[i]);
 67         }
 68     }
 69 }
 70 int main() {
 71 #ifndef ONLINE_JUDGE
 72     freopen("in", "r", stdin);
 73     //freopen("out", "w", stdout);
 74 #endif
 75     int T;
 76     scanf("%d", &T);
 77     while(T--) {
 78         scanf("%d", &n);
 79         Graph tree(n);
 80         for(int i=0; i<n-1; ++i) {
 81             int a, b;
 82             scanf("%d%d", &a, &b);
 83             --a; --b;
 84             tree.addEdge(a, b);
 85             tree.addEdge(b, a);
 86         }
 87         scanf("%d", &m);
 88         for(int i=0; i<n; ++i) {
 89             int num;
 90             scanf("%d", &num);
 91             tree.tower[i].resize(num);
 92             for(auto & p : tree.tower[i]) {
 93                 scanf("%d%d", &p.first, &p.second);
 94             }
 95         }
 96         dfs(tree, 0, -1);
 97         int ans=0;
 98         for(auto x : tree.f[0]) ans=max(ans, x);
 99         printf("%d\n", ans);
100     }
101     return 0;
102 }
View Code

 

posted on 2015-10-07 19:39  shjwudp  阅读(273)  评论(0编辑  收藏  举报