【树形DP】HDU 4003 Find Metal Mineral

通道:http://acm.hdu.edu.cn/showproblem.php?pid=4003

题意:边权树. 有K个机器人从S点出发, 问让机器人遍历所有边,最少花费值多少

思路:dp[i][j]表示以i为根的树用掉j个人。dp[i][0]表示用了一个人又回到上面的点,然后就是分组背包,每个组必选一个,这就有个特殊技巧,就是我们先将dp[son][0]放进背包,如果该组里有更好的选择,那么就会换掉这个物品,否则的话这个物品就是最好的选择。这样保证每组必定选了一个

代码:

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
using namespace std;

const int MAXN=10010;

struct Node
{
    int to;
    int next;
    int cost;
}edge[MAXN*2];
int head[MAXN];
int tol;

int dp[MAXN][11];

void init()
{
    memset(head,-1,sizeof(head));
    tol=0;
    memset(dp,0,sizeof(dp));
}

void add(int a,int b,int val)
{
    edge[tol].to=b;
    edge[tol].cost=val;
    edge[tol].next=head[a];
    head[a]=tol++;
    edge[tol].to=a;
    edge[tol].cost=val;
    edge[tol].next=head[b];
    head[b]=tol++;
}

int N,K;

void dfs(int u,int pre)
{
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==pre)continue;
        dfs(v,u);
        for(int k=K;k>=0;k--)
        {
            dp[u][k]+=dp[v][0]+2*edge[i].cost;
            for(int j=1;j<=k;j++)
              dp[u][k]=min(dp[u][k],dp[u][k-j]+dp[v][j]+j*edge[i].cost);
        }
    }
}
int main()
{
    int S;
    int a,b,val;
    while(scanf("%d%d%d",&N,&S,&K)!=EOF)
    {
        init();
        for(int i=1;i<N;i++)
        {
            scanf("%d%d%d",&a,&b,&val);
            add(a,b,val);
        }
        dfs(S,-1);
        printf("%d\n",dp[S][K]);
    }
    return 0;
}
View Code

 

posted @ 2014-11-03 19:42  mithrilhan  阅读(167)  评论(0编辑  收藏  举报