HDU1011

来源:互联网 发布:淘宝印度大麻种子 编辑:程序博客网 时间:2024/06/05 11:45

Starship Troopers

题目链接

分类dfs and similar dp trees

1.题意概述

  • 出每个房间拥有的BUG数和能得到的能量数,然后给出每个房间的树形联通图,要到下一个房间必须攻破上一个房间,每个士兵最多消灭20个BUG,就算不足20个BUG也要安排一个士兵。

2.解题思路

  • 树形dp入门题,对于每个房间,除去它本身需要的士兵,其他士兵就可以提供给它的子房间(子树),而子房间的最优选择也提供给了父节点,设dp[i][j]表示以i为根派j个士兵的最大价值,那么转移方程就是dp[i][j]=max(dp[i][jk]+dp[son[i]][k])

3.AC代码

#include <bits/stdc++.h>#define INF 0x3f3f3f3f#define maxn 100010#define lson root << 1#define rson root << 1 | 1#define lent (t[root].r - t[root].l + 1)#define lenl (t[lson].r - t[lson].l + 1)#define lenr (t[rson].r - t[rson].l + 1)#define N 101#define eps 1e-6#define pi acos(-1.0)#define e exp(1.0)using namespace std;const int mod = 1e9 + 7;typedef long long ll;typedef unsigned long long ull;int cost[N], brain[N], dp[N][N], n, m;  // dp[u][p] p个士兵占领以u为根节点的概率最大值vector<int> mp[N];void dfs(int u, int pa){    for (int i = cost[u]; i <= m; i++)        dp[u][i] = brain[u];    int sz = mp[u].size();    for (int i = 0; i < sz; i++)    {        int v = mp[u][i];        if (v != pa)        {            dfs(v, u);            for (int j = m; j >= cost[u]; j--)                for (int k = 1; k <= j - cost[u]; k++)                    dp[u][j] = max(dp[u][j], dp[u][j - k] + dp[v][k]);        }    }}int main(){    while (~scanf("%d%d", &n, &m), n != -1 && m != -1)    {        for (int i = 0; i < n; i++)        {            int bug;            scanf("%d%d", &bug, &brain[i]);            cost[i] = (bug + 19) / 20;            mp[i].clear();        }        for (int i = 0; i < n - 1; i++)        {            int u, v;            scanf("%d%d", &u, &v);            u--;            v--;            mp[u].push_back(v);            mp[v].push_back(u);        }        if (m == 0)        {            puts("0");            continue;        }        memset(dp, 0, sizeof dp);        dfs(0, -1);        printf("%d\n", dp[0][m]);    }    return 0;}
原创粉丝点击