HDU 1011 Starship Troopers

树形DP。这题折腾了一天,很开心,总算是独立AC了。题意读了好几遍,发现并不是很明确。

注意这个坑:即使该洞bug数为0,要获得该洞brain值,也需要至少一人经过该洞穴,但这个人可以不停留在这个点

估计这题代码我写的最长了。。。。有好多地方可以简化。。。

留几组数据:

第一组:答案是200

2 1
0 100
20 100
1 2

第二组:答案是100

2 1
20 100
0 100
1 2

第三组:答案是9

5 2
0 1
0 1
0 5
0 1
0 2
1 2
1 3
2 4
2 5

#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<vector>
#include<algorithm>
using namespace std;

const int maxn = 100 + 10;
int dp[maxn][maxn];
int flag[maxn], tmp[maxn];
int n, m;
int cost[maxn], val[maxn];
int c[maxn], w[maxn];
bool vis[maxn];
vector<int>tree[maxn];
vector<int>treeFlag[maxn];

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

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

        tree[v].push_back(u);
        treeFlag[v].push_back(0);
    }
}

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 == 1)
    {
        int c;
        if (cost[now] % 20 == 0) c = cost[now] / 20;
        else c = cost[now] / 20 + 1;
        if (cost[now] == 0) c = 1;
        if (c <= m) dp[now][c] = val[now];
        return;
    }

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

    if (cost[now] != 0)
    {
        int costNow;
        if (cost[now] % 20 == 0) costNow = cost[now] / 20;
        else costNow = cost[now] / 20 + 1;

        memset(tmp, -1, sizeof tmp); tmp[0] = 0;

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

            int u = 0;
            int id = tree[now][i];
            for (int j = 1; j <= m - costNow; j++)
            if (dp[id][j] != -1)
                c[u] = j, w[u++] = dp[id][j];

            memset(flag, -1, sizeof flag);
            flag[0] = 0;

            for (int k = 0; k<u; k++)
            {
                for (int j = m - costNow; j >= c[k]; j--)
                if (tmp[j - c[k]] != -1)
                if (tmp[j - c[k]] + w[k]>tmp[j] && tmp[j - c[k]] + w[k]>flag[j])
                    flag[j] = tmp[j - c[k]] + w[k];
            }
            for (int j = 0; j <= m - costNow; j++) if (flag[j]>tmp[j]) tmp[j] = flag[j];
        }

        for (int i = 0; i <= m - costNow; i++)
        if (tmp[i] != -1)
            dp[now][i + costNow] = tmp[i] + val[now];
    }

    else
    {
        memset(tmp, -1, sizeof tmp); tmp[0] = 0;

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

            int u = 0;
            int id = tree[now][i];
            for (int j = 1; j <= m; j++)
            if (dp[id][j] != -1)
                c[u] = j, w[u++] = dp[id][j];

            memset(flag, -1, sizeof flag);
            flag[0] = 0;

            for (int k = 0; k<u; k++)
            {
                for (int j = m; j >= c[k]; j--)
                if (tmp[j - c[k]] != -1)
                if (tmp[j - c[k]] + w[k]>tmp[j] && tmp[j - c[k]] + w[k]>flag[j])
                    flag[j] = tmp[j - c[k]] + w[k];    
            }
            for (int j = 0; j <= m; j++) if (flag[j]>tmp[j]) tmp[j] = flag[j];
        }

        if (tmp[1] == -1) dp[now][1] = val[now];
        else dp[now][1] = tmp[1] + val[now];
        for (int i = 2; i <= m; i++) if (tmp[i] != -1) dp[now][i] = tmp[i] + val[now];
    }
}

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

int main()
{
    while (~scanf("%d%d", &n, &m))
    {
        if (n == -1 && m == -1) break;
        init();
        read();
        work();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/5184472.html