Find Metal Mineral HDU - 4003 (树形DP)

Find Metal Mineral

 题目连接:HDU - 4003 

题意:火星上出金矿了!!!排k个机器人到S点,问机器人找完所有金矿后,最短的移动距离;如果只有一个机器人,他就要找遍所有金矿就会走重复的路,直到找到最后一个矿;如果有两个机器人,他俩就可以分头行动;

思路:每个节点都可以分0~k个机器人,但是这里有两点要注意:

1:此k非彼k,这里的k指的是该节点的父亲分到的机器人的数量;

2:此0非彼0,0并不表示不分配机器人了,而是只有一个机器人分配过来,并且最终返回父节点;

设dp[i][j]表示i节点分配j个机器人的最短移动距离,dp[i][j]=min(dp[i][j-k]+dp[son][k] | 0<=k<=j)(son是i的子节点)

#include <bits/stdc++.h>
using namespace std;
const int maxn=10010;
struct node{
	int v, w, nxt;
	node(){}
	node(int v0, int w0, int n){
		v=v0, w=w0, nxt=n;
	}
}edge[maxn<<1];
int head[maxn], cnt;
void add(int u, int v, int w){
	edge[cnt]=node(v, w, head[u]);
	head[u]=cnt++;
}
int dp[maxn][15];
void dfs(int u, int fa, int k){
	for(int i=head[u]; i!=-1; i=edge[i].nxt){
		int son=edge[i].v, dis=edge[i].w;
		if(son==fa) continue;
		dfs(son, u, k);
		for(int j=k; j>=0; j--){
			dp[u][j]+=dp[son][0]+dis*2;
			for(int p=1; p<=j; p++){
				dp[u][j]=min(dp[u][j], dp[u][j-p]+dp[son][p]+dis*p);
			}
		}
	}
}
int main(){
	int N, S, K;
	while(~scanf("%d%d%d", &N, &S, &K)){
		cnt=0;
		memset(head, -1, sizeof(head));
		memset(dp, 0, sizeof(dp));
		for(int i=1; i<N; i++){
			int x, y, w;
			scanf("%d%d%d", &x, &y, &w);
			add(x, y, w);
			add(y, x, w);
		}
		dfs(S, S, K);
		printf("%d\n", dp[S][K]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Sirius_han/article/details/81318834