标签:
题意:求K个机器人从同一点出发,遍历所有点所需的最小花费
链接:点我
转移方程: dp[i][j]=min(dp[i][j],dp[i][j*k],dp[son[i]][k]+len(i,son[i])*k)
方程还是比较好写的,主要是要遍历所有的点
下面我们分析一下第一个样例
1
/ \
/ \
2 3
我们派了一个机器人去3,那么1这一点就没有机器人了,既然需要遍历所有的点,则需要1->2已经走过,即从1出发,然后又返回了1,这时候没有机器人也可以访问完下面的点
那么dp[i][0]表示的就是一个机器人从i点出发,走一条路然后返回到i的值,则我们在递推j的时候,每次先加上这个值,即可以保证所有路都走过一遍
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3f3f3f; 11 const double eps=1e-5; 12 typedef long long ll; 13 #define cl(a) memset(a,0,sizeof(a)) 14 #define ts printf("*****\n"); 15 const int MAXN=10010; 16 int dp[MAXN][11],val[MAXN],head[MAXN]; 17 int n,m,tt,tot; 18 struct Edge 19 { 20 int to,next,val; 21 }edge[MAXN*2]; 22 void addedge(int u,int v,int w) 23 { 24 edge[tot].to=v; 25 edge[tot].next=head[u]; 26 edge[tot].val=w; 27 head[u]=tot++; 28 } 29 void init() 30 { 31 memset(head,-1,sizeof(head)); 32 tot=0; 33 memset(dp,0,sizeof(dp)); 34 } 35 void dfs(int u,int pre) 36 { 37 for(int i=head[u];i!=-1;i=edge[i].next) 38 { 39 int v=edge[i].to; 40 if(v==pre) continue; 41 dfs(v,u); 42 for(int j=m;j>=0;j--) 43 { 44 dp[u][j]+=dp[v][0]+2*edge[i].val; 45 for(int k=1;j-k>=0;k++) 46 { 47 dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v][k]+k*edge[i].val); 48 } 49 } 50 } 51 } 52 int main() 53 { 54 int i,j,k; 55 #ifndef ONLINE_JUDGE 56 freopen("1.in","r",stdin); 57 #endif 58 int st; 59 int a,b,val; 60 while(scanf("%d%d%d",&n,&st,&m)!=EOF) 61 { 62 init(); 63 for(i=1;i<n;i++) 64 { 65 scanf("%d%d%d",&a,&b,&val); 66 addedge(a,b,val); 67 addedge(b,a,val); 68 } 69 dfs(st,-1); 70 printf("%d\n",dp[st][m]); 71 } 72 }
hdu 4003 树形dp+分组背包 2011大连赛区网络赛C
标签:
原文地址:http://www.cnblogs.com/cnblogs321114287/p/4329133.html