题意:有一个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 }