HDU 1011 Starship Troopers (树形DP, 简单题目)

来源:互联网 发布:mac程序如何卸载 编辑:程序博客网 时间:2024/06/05 11:08

Problem Description

  • 题目链接: HDU 1011 Starship Troopers

  • 题意:

    • 副本: 有n个room, 每个room 都有a个怪物, b点经验值, 每个room之间为双向边, 构成一颗树(仅有n-1条边)
    • 你: 拥有m个士兵, 一个士兵可以打20个怪物
    • 限制: 要拿下某个room的b点经验,必须留下x个士兵将所有的怪物消灭,必须将当前room中所有怪物清除掉才能进入下一个room (x*20>=a)
    • 提问:能获得的最大经验值为多少?
  • 输入:
    • 给定n,m
    • 接下去n行,第i行有a, b两个非负数, 表示第i个room有a个怪物,b点经验值
    • 接下去n-1行, 每行输入u, v, 表示u和v有之间存在一条边.
  • 解决方案:
    • 分析 :
      • 每个room需要留下的士兵的数目的范围为 [(a+19)/20, m]
      • 假设当前room留下了j个士兵,则能进入下一个room的士兵数目范围为[1, m-j]
    • 构造dp方程
      • dp[fa][j+k] = max(dp[fa][j+k], dp[fa][j]+dp[son][k];
        • 其中 j+k 表示进入第 fa 个room的士兵数目
        • j 表示留在第 fa 个room的士兵数目
        • k 表示进入第 fa 个room的下一个相连的第son个room的士兵数目
#include<bits/stdc++.h>using namespace std;#define mp make_pair#define pb push_back#define fir first#define sec second#define repp(i, a, b) for(int i=(b); i>=(a); --i)#define rep(i,a,b) for (int i=(a); i<=(b); ++i)#define de(x) cout<< #x << " => " << (x) << endl#define ms(a, b) memset(a, b, sizeof(a))typedef long long ll;typedef pair<int,int> pii;typedef vector<int> vi;const int inf = 0x3f3f3f3f;const double PI=acos(-1);const double eps=1e-9;inline void file_put() {    freopen("in.txt", "r", stdin);//    freopen("out.txt", "w", stdout);}const int maxn = 1e2+5;vi e[maxn];struct node{    int bug, brain;}p[maxn];int n, m;int dp[maxn][maxn];bool mark[maxn];void dfs(int u){    mark[u] = true;    int len = e[u].size();    int cost;    cost = (p[u].bug+19)/20;    rep(i, cost, m){        dp[u][i] = p[u].brain;    }    rep(i, 0, len-1){        int v = e[u][i];        if(mark[v]) continue;        dfs(v);        repp(j, cost, m){            rep(k, 1, m-j){                if(dp[v][k]) {                    dp[u][j+k] = max(dp[u][j+k], dp[u][j]+dp[v][k]);                }            }        }    }    return ;}int main() {//  file_put();    while(~scanf("%d %d", &n, &m), n!=-1 || m!=-1){        rep(i, 1, n) e[i].clear();         ms(mark, false);        ms(dp, 0);        rep(i, 1, n){            scanf("%d %d", &p[i].bug, &p[i].brain);        }        int u, v;        rep(i, 1, n-1){            scanf("%d %d", &u, &v);            e[u].pb(v);            e[v].pb(u);        }        if(!m) {            printf("0\n");            continue;        }        dfs(1);        printf("%d\n", dp[1][m]);    }    return 0;}
阅读全文
0 0
原创粉丝点击