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;
    }
  • 相关阅读:
    Java实现 LeetCode 394 字符串解码
    Java实现 LeetCode 394 字符串解码
    Java实现 LeetCode 392 判断子序列
    Java实现 LeetCode 392 判断子序列
    Java实现 LeetCode 392 判断子序列
    Java实现 LeetCode 391 完美矩形
    Java实现 LeetCode 391 完美矩形
    Java实现 LeetCode 391 完美矩形
    Java实现 LeetCode 390 消除游戏
    Java实现 LeetCode 390 消除游戏
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4782768.html
Copyright © 2011-2022 走看看