hdu 4003

题意:有一个n节点的树,开始在点s上有k个机器人,求最小的距离使得k个机器人走完所有边

分析:很明显可以想到,每一颗子树分给他几个机器人走可以得到最小值,dp[i][j],表示分给以i为根节点的子树给j个机器人走完的最短距离,j=0也不难理解就是给这个子树一个机器人,走完所有边再回到根节点的最小值

因为还要走回来,所以要走的距离肯定要大的多,先算成走回来的距离,再思考分配给下面的儿子几个机器人,如果走回来dp[u][i]+=dp[v][0]+x*w;

j个机器人不走回来,那么机器人走到儿子的总距离就是j*w

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e4+5;
 4 vector<int> g[maxn],val[maxn];
 5 int dp[maxn][11];
 6 int n,s,k;
 7 
 8 void dfs(int u,int f){
 9     for(int i=0;i<g[u].size();i++){
10         int v=g[u][i],w=val[u][i];
11         if(v==f)continue;
12         dfs(v,u);
13         for(int i=k;i>=0;i--){
14             dp[u][i]+=dp[v][0]+2*w;//先初始化为返回的
15             for(int j=1;j<=i;j++)
16                 dp[u][i]=min(dp[u][i],dp[u][i-j]+dp[v][j]+j*w);
17         }
18     }
19 }
20 
21 int main(){
22     //freopen("in","r",stdin);
23     ios::sync_with_stdio(false);
24     while(cin>>n>>s>>k){
25         for(int i=0;i<=n;i++)g[i].clear(),val[i].clear();
26         for(int i=1;i<n;i++){
27             int u,v,w;cin>>u>>v>>w;
28             g[u].push_back(v);g[v].push_back(u);
29             val[u].push_back(w);val[v].push_back(w);
30         }
31         memset(dp,0,sizeof(dp));
32         dfs(s,-1);
33         cout<<dp[s][k]<<endl;
34     }
35     return 0;
36 }
View Code
原文地址:https://www.cnblogs.com/jihe/p/5799530.html