• uvalive4015 (树上背包)


    给一棵树,边上有权值,然后给一个权值x,问从根结点出发, 走不超过x的距离,最多能经过多少个结点。

    走过的点可以重复走,所以可以从一个分支走下去,然后走回来,然后再走另一个分支

    dp[u][j][0] 表示从u出发,走了j个点,然后不回到u点的最小花费

    dp[u][j][1] 表示从u出发,走了j个点,然后回到u点的最小花费

    dp[u][j][0] = min(dp[u][j][0], dp[v][k][0]+dp[u][j-k][1]+dis, dp[v][k][1]+dp[u][j-k][0]+2*dis);

    可能是当前这个分支不回到u点,那么就是dp[v][k][0] + dp[u][j-k][1] +dis

    可能是当前这个分支回到u点(那么u->v的边走两次,那么就是2*dis),但是以前的分支不回到u点,dp[v][k][1] + dp[u][j-k][0] + 2*dis

    dp[u][j][1] = min(dp[u][j][1], dp[v][k][1]+ dp[u][j-k][1] + dis)

    #pragma warning(disable:4996)
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    #include <math.h>
    #include <map>
    #include <set>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <bitset>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <functional>
    const int INF = 1 << 30;
    
    /*
    
    
    树形背包
    */
    const int N = 500 + 10;
    struct Edge
    {
        int to, dis, next;
    }g[N*2];
    int head[N], e, fa[N];
    int dp[N][N][2];
    int size[N];
    int n, u, v, dis, query[1111];
    void addEdge(int u, int v, int dis)
    {
        g[e].to = v;
        g[e].dis = dis;
        g[e].next = head[u];
        head[u] = e++;
    }
    void init()
    {
        memset(dp, 0x7f7f7f7f, sizeof(dp));
        memset(head, -1, sizeof(head));
        memset(fa, -1, sizeof(fa));
        e = 0;
    }
    void dfs(int u, int fa)
    {
        dp[u][1][0] = dp[u][1][1] = 0;
        size[u] = 1;
        for (int i = head[u];i != -1;i = g[i].next)
        {
            int v = g[i].to;
            if (v == fa) continue;
            dfs(v, u);
            size[u] += size[v];
            for (int j = size[u];j >= 1;--j)
                for (int k = 1;k <= size[v]; ++k)
                {
                    dp[u][j][0] = std::min(dp[u][j][0], std::min(dp[u][j-k][1]+dp[v][k][0] + g[i].dis, dp[u][j-k][0]+dp[v][k][1] + g[i].dis * 2));
                    dp[u][j][1] = std::min(dp[u][j][1], dp[u][j-k][1] + dp[v][k][1] + g[i].dis * 2);
                }
            
        }
    }
    int main()
    {
        int tcase = 1;
        while (scanf("%d", &n) ,n)
        {
            init();
            for (int i = 1;i < n;++i)
            {
                scanf("%d%d%d", &u, &v, &dis);
                addEdge(v, u, dis);
                fa[u] = v;
            }
            int root;
            for (int i = 0;i < n;++i)
                if (fa[i] == -1)
                    root = i;
            int q, x;
            dfs(root, -1);
            scanf("%d", &q);
            printf("Case %d:
    ", tcase++);
            while (q--)
            {
                int ans;
                scanf("%d", &x);
                for (int i = 1;i <= n;++i)
                    if (dp[root][i][0] <= x || dp[root][i][1] <= x)
                        ans = i;
                printf("%d
    ", ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    Scrapy snippets
    HttpClient4的cookie rejected问题,以及如何消除该warning输出
    简单的python smtp发邮件代码
    FTP服务器:Proftpd
    “当HTML5来敲门”专题沙龙杂记
    Titanium Mobile 1.6版本发布
    给同学们分享一些面试经验
    用CSS3实现动画进度条
    3天内构建Facebook Web应用的经验之谈
    仅用CSS创建立体旋转幻灯片
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4782768.html
Copyright © 2020-2023  润新知