您的位置:首页 > 其它

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

2017-01-19 09:55 363 查看
题意:给你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[s
9089
on][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 10120
using 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: