zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    闲话: 恭喜园子里的MVP一下, 同时问所有奋斗在技术领域的兄弟过节好~
    随便说两句: 表设计兼一些设计分析的讨论
    是他妈傻子写的么?
    Utility Wish List
    我终于有个偶像了
    也论标准: 统一是啥好事情?
    linux 编程学习笔记(1)搭建c(c++)开发环境
    Immutable Collections(2)ImmutableList<T>实现原理.(上)
    托管代码的进程注入&CLR宿主
    .NET安全揭秘系列博文索引
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4782768.html
Copyright © 2011-2022 走看看