HDU 4003 Find Metal Mineral(树形dp + 分组背包)

来源:互联网 发布:oracle数据库怎么用 编辑:程序博客网 时间:2024/04/24 16:57

题意:给你n个点,n - 1条边,k个机器人,s为起点,问遍历所有点的最小花费。

————————————————————————————————————————————————

【转载】:

dp[i][j]表示对于以i结点为根结点的子树,放j个机器人所需要的权值和。 

当j=0时表示放了一个机器人下去,遍历完结点后又回到i结点了。状态转移方程类似背包 

如果最终的状态中以i为根结点的树中有j(j>0)个机器人,那么不可能有别的机器人r到了这棵树后又跑到别的树中去 

因为那样的话,一定会比j中的某一个到达i后跑与r相同的路径再回到i,再接着跑它的路径要差(多了一条i回去的边) 

这样的话,如果最后以i为根结点的树中没有机器人,那么只可能是派一个机器人下去遍历完后再回来

————————————————————————————————————————————————

此题还用到了分组背包的思想附上分组背包的伪代码,详细可去看一下背包九讲

使用一维数组的“分组背包”伪代码如下:

for 所有的组i

    for v=V..0

        for 所有的k属于组i

            f[v]=max{f[v],f[v-c[k]]+w[k]}

思路:对于每一个结点运用一次分组背包,假如i有n个儿子,每个儿子是一个分组,分组里的选项有dp[son][0],dp[son][1]........dp[son][k],跟分组背包又不同的一点是每个分组都必需选一项,所以我们可以事先将dp[son][0]加到dp[i][k]上,通过dp看是否有比这更优解。

附上ac代码:

#include <algorithm>#include <iostream>#include <cstring>#include <string>#include <queue>#include <stack>#include <list>#include <map>#include <set>#define For0(n) for(int i = 0; i < n; i++)#define For1(n) for(int i = 1; i <= n; i++)#define Forn_m(n,m) for(int i = n; i <= m; i++)#define MAX 10120using namespace std;struct Edge{    int to, length;};vector <Edge> vec[MAX];int n, s, k;int dp[MAX][12];bool vis[MAX];void dfs(int root){    int num = vec[root].size();    vis[root] = true;    For0(num)    {        if (vis[vec[root][i].to])            continue;        dfs(vec[root][i].to);        for (int x = k; x >= 0; x--)        {            dp[root][x] += dp[vec[root][i].to][0] + 2*vec[root][i].length;            for (int y = 1; y <= x; y++)                dp[root][x] = min(dp[root][x], dp[root][x - y]                    + dp[vec[root][i].to][y] + y * vec[root][i].length);        }    }}int main(){    int u, v;    Edge temp;    while (scanf("%d%d%d", &n, &s, &k) != EOF)    {        memset(vis, 0, sizeof(vis));        memset(dp, 0, sizeof(dp));        For0(MAX)            vec[i].clear();        Forn_m(2, n)        {            scanf("%d%d%d", &u, &temp.to, &temp.length);            vec[u].push_back(temp);                v = temp.to;            temp.to = u;            u = v;            vec[u].push_back(temp);        }        dfs(s);        printf("%d\n", dp[s][k]);    }    return 0;}



0 0
原创粉丝点击