• HDU 4003 Find Metal Mineral


    这个题是POJ1849的加强版。

    先说一个很重要的结论,下面两种方法都是从这个结论出发的。

    一个人从起点遍历一颗树,如果最终要回到起点,走过的最小权值就是整棵树的权值的2倍

    而且K个人的情况也是如此,大不了只有一个人走,其他K-1个人待着不动就行了。

    而题目中说了这些人不比回到原点,所以就想办法考虑哪些多走的路程,最后用整棵树权值2倍减去就好了。

    一、

    多数人的做法是分组背包,推荐这篇博客

    里面的状态的定义并不复杂,和网上那些千篇一律的做法比,思路很新颖。

    f(i, j)表示i为根的子树有j个机器人出发,遍历这棵子树可以少走多少路。

    最终答案为sum - f(S, K)

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <vector>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 const int maxn = 10000 + 10;
     9 const int maxk = 12;
    10 
    11 int n, s, k;
    12 
    13 vector<int> G[maxn], C[maxn];
    14 
    15 int f[maxn][maxk];
    16 
    17 void DP(int u, int fa)
    18 {
    19     for(int i = 0; i < G[u].size(); i++)
    20     {
    21         int v = G[u][i], w = C[u][i];
    22         if(v == fa) continue;
    23         DP(v, u);
    24         for(int i = k; i >= 1; i--)
    25             for(int j = 1; j <= i; j++)
    26                 f[u][i] = max(f[u][i], f[u][i-j] + f[v][j] + (2 - j) * w);
    27     }
    28 }
    29 
    30 int main()
    31 {
    32     while(scanf("%d%d%d", &n, &s, &k) == 3)
    33     {
    34         for(int i = 1; i <= n; i++) { G[i].clear(); C[i].clear(); }
    35 
    36         int sum = 0;
    37         for(int i = 1; i < n; i++)
    38         {
    39             int u, v, w; scanf("%d%d%d", &u, &v, &w);
    40             sum += w;
    41             G[u].push_back(v); C[u].push_back(w);
    42             G[v].push_back(u); C[v].push_back(w);
    43         }
    44         sum <<= 1;
    45 
    46         memset(f, 0, sizeof(f));
    47         DP(s, 0);
    48         printf("%d
    ", sum - f[s][k]);
    49     }
    50 
    51     return 0;
    52 }
    代码君

    二、

    这篇博客中

    还有一种更为巧妙的做法,就是每次从起点出发找到一条最长的路径,记录下路径的长度,然后把这条路径上边的权值变为相反数。注意,已经变为负权的边就不再变回去了。

    这样找K次最长的路径,然后加起来就是可以最多少走多少路。

    为什么要把权值变成负的,因为你第二次第三次再走这条路的时候,就表示少走了负的权值,也就是多走了。如果出现所有的路都是负权的情况,那么树中最长路的路径就是0,也就是机器人原地不动。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <vector>
     6 using namespace std;
     7 
     8 const int maxn = 10000 + 10;
     9 
    10 struct Edge
    11 {
    12     int u, v, w;
    13     Edge(int u, int v, int w):u(u), v(v), w(w) {}
    14 };
    15 
    16 vector<Edge> edges;
    17 vector<int> G[maxn];
    18 
    19 void AddEdge(int u, int v, int w)
    20 {
    21     edges.push_back(Edge(u, v, w));
    22     edges.push_back(Edge(v, u, w));
    23     int m = edges.size();
    24     G[u].push_back(m - 2);
    25     G[v].push_back(m - 1);
    26 }
    27 
    28 int n, s, k;
    29 
    30 int len, id;
    31 int pre[maxn];
    32 
    33 void dfs(int u, int fa, int d)
    34 {
    35     if(d > len) { len = d; id = u; }
    36     for(int i = 0; i < G[u].size(); i++)
    37     {
    38         Edge& e = edges[G[u][i]];
    39         int v = e.v;
    40         if(v == fa) continue;
    41         pre[v] = G[u][i];
    42         dfs(v, u, d + e.w);
    43     }
    44 }
    45 
    46 int main()
    47 {
    48     while(scanf("%d%d%d", &n, &s, &k) == 3)
    49     {
    50         edges.clear();
    51         int tot = 0;
    52         for(int i = 1; i <= n; i++) G[i].clear();
    53         for(int i = 1; i < n; i++)
    54         {
    55             int u, v, w; scanf("%d%d%d", &u, &v, &w);
    56             tot += w;
    57             AddEdge(u, v, w);
    58         }
    59         tot <<= 1;
    60 
    61         int ans = 0;
    62         for(int i = 0; i < k; i++)
    63         {
    64             len = 0, id = s;
    65             pre[s] = -1;
    66             dfs(s, 0, 0);
    67             if(id == s) continue;
    68             ans += len;
    69             for(int u = id; u != s; u = edges[pre[u]].u)
    70             {
    71                 int& w = edges[pre[u]].w;
    72                 if(w > 0) w = -w;
    73             }
    74         }
    75 
    76         printf("%d
    ", tot - ans);
    77     }
    78 
    79     return 0;
    80 }
    代码君
  • 相关阅读:
    数组指针的一个易错点
    jQuery on()方法
    php 前一天或后一天的日期
    用jQuery监听浏览器窗口的变化
    jquery获取json对象中的key小技巧
    JQuery操作元素的属性与样式及位置
    用JQuery操作元素的style属性
    如何删除jsPlumb连接
    jsPlumb.jsAPI阅读笔记(官方文档翻译)
    Jquery empty() remove() detach() 方法的区别
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4691931.html
Copyright © 2020-2023  润新知