zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    (设计模式)组合模式
    redis 集群部署 (linux)
    redis 集群 配置文件
    redis 外部访问配置(bind正确配置)
    (设计模式)桥模式
    (springboot)freemarker(二)
    (springboot)入门(一)
    (设计模式)抽象工厂
    (设计模式)建造者模式
    (设计模式)原型
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5184472.html
Copyright © 2011-2022 走看看