HDU 4044 GeoDefense

树形DP,和背包差不多。dp[now][x]表示now这个节点的子树上,花费为x的时候,获得的最大防御能力(保证敌方HP<=0)

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

const int maxn = 1000 + 10;
int T, n, m;
vector<int>tree[maxn];
struct kind
{
    int price;
    int power;
    kind(int a, int b){ price = a; power = b; }
};
vector<kind>v[maxn];
bool vis[maxn];
int dp[maxn][200 + 10];
int flag[200 + 10], tmp[200 + 10];

void init()
{
    for (int i = 0; i <= n; i++) tree[i].clear();
    for (int i = 0; i <= n; i++) v[i].clear();
    memset(vis, 0, sizeof vis);
    memset(dp, -1, sizeof dp);
}

void read()
{
    scanf("%d", &n);
    for (int i = 1; i <= n - 1; i++)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        tree[u].push_back(v);
        tree[v].push_back(u);
    }
    scanf("%d", &m);

    for (int i = 1; i <= n; i++)
    {
        int ki;
        scanf("%d", &ki);
        while (ki--)
        {
            int pricei, poweri;
            scanf("%d%d", &pricei, &poweri);
            kind k(pricei, poweri);
            v[i].push_back(k);
        }
    }
}

void dfs(int now)
{
    bool fail = 1;
    for (int i = 0; i<tree[now].size(); i++)
        if (!vis[tree[now][i]]) fail = 0;

    if (fail)
    {
        for (int i = 0; i<v[now].size(); i++)
            dp[now][v[now][i].price] = max(dp[now][v[now][i].price], v[now][i].power);
        return;
    }

    bool d[maxn];
    memset(d, 0, sizeof d);
    for (int i = 0; i<tree[now].size(); i++)
    {
        if (vis[tree[now][i]]) continue;

        int id = tree[now][i];
        vis[id] = 1; dfs(id); d[i] = 1;
    }

    memset(flag, -1, sizeof flag);

    bool first = 1;

    for (int i = 0; i<tree[now].size(); i++)
    {
        if (!d[i]) continue;

        int id = tree[now][i];

        if (first)
        {
            first = 0;
            for (int j = 0; j <= m; j++) flag[j] = dp[id][j];
        }

        else
        {
            memset(tmp, -1, sizeof tmp);
            for (int j = 0; j <= m; j++)
                for (int k = 0; k <= m; k++)
                    if (dp[id][j] != -1 && flag[k] != -1 && j + k <= m)
                        tmp[j + k] = max(tmp[j + k], min(dp[id][j], flag[k]));
            for (int j = 0; j <= m; j++) flag[j] = tmp[j];
        }
    }

    for (int i = 0; i<v[now].size(); i++)
        for (int j = m; j >= v[now][i].price; j--)
            if (flag[j - v[now][i].price] != -1)
                dp[now][j] = max(dp[now][j], flag[j - v[now][i].price] + v[now][i].power);

    for (int i = 0; i <= m; i++) dp[now][i] = max(dp[now][i], flag[i]);

    for (int i = 0; i<v[now].size(); i++)
        dp[now][v[now][i].price] = max(dp[now][v[now][i].price], v[now][i].power);
}

void work()
{
    vis[1] = 1;
    dfs(1);
    int ans = 0;
    for (int i = 0; i <= m; i++) ans = max(ans, dp[1][i]);
    printf("%d
", ans);
}

int main()
{
    scanf("%d", &T);
    while (T--)
    {
        init();
        read();
        work();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/5186148.html