HDU 1011 Starship Troopers (樹形DP, 簡單題目)

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章