标签:
依旧是状态分组
——求K个机器人从同一点出发,遍历所有点所需的最小花费
1 /* 2 HDU 4003 3 树形DP+只能选一个物品的分组背包 4 5 dp[pos][num]表示以pos为根节点的子树下,用去num个机器人,所得到的最小值 6 特别的是当num==0的时候,dp[pos][0]表示用一个机器人去走完所有子树,最后又回到pos这个节点 7 状态转移:dp[pos][num]=min∑{dp[pos_j][num_j]+w_j},pos_j是pos的所有儿子, 8 9 10 为了让分组背包只选一个,首先让dp[u][0]如背包 11 12 使用一维数组的“分组背包”伪代码如下: 13 for 所有的组i 14 15 for v=V..0 16 17 for 所有的k属于组i 18 19 f[v]=max{f[v],f[v-c[k]]+w[k]} 20 21 22 */ 23 24 #include<stdio.h> 25 #include<algorithm> 26 #include<string.h> 27 #include<iostream> 28 using namespace std; 29 30 const int MAXN=10010; 31 32 struct Node 33 { 34 int to; 35 int next; 36 int cost;//该条路径的花费 37 }edge[MAXN*2];//无向树 38 int head[MAXN]; 39 int tol; 40 41 int dp[MAXN][11];//dp[i][j]表示以i为根的树用掉j个人。dp[i][0]表示用了一个人又回到上面的点 42 43 void init() 44 { 45 memset(head,-1,sizeof(head)); 46 tol=0; 47 memset(dp,0,sizeof(dp)); 48 } 49 50 void add(int a,int b,int val) 51 { 52 edge[tol].to=b; 53 edge[tol].cost=val; 54 edge[tol].next=head[a]; 55 head[a]=tol++; 56 edge[tol].to=a; 57 edge[tol].cost=val; 58 edge[tol].next=head[b]; 59 head[b]=tol++; 60 } 61 62 int N,K; 63 64 void dfs(int u,int pre) 65 { 66 for(int i=head[u];i!=-1;i=edge[i].next) 67 { 68 int v=edge[i].to; 69 if(v==pre)continue; 70 dfs(v,u); 71 for(int k=K;k>=0;k--) 72 { 73 dp[u][k]+=dp[v][0]+2*edge[i].cost;//先把dp[u][0]放进背包,保证至少选一个 74 // 分组背包 75 for(int j=1;j<=k;j++) 76 dp[u][k]=min(dp[u][k],dp[u][k-j]+dp[v][j]+j*edge[i].cost); 77 } 78 } 79 } 80 int main() 81 { 82 int S; 83 int a,b,val; 84 while(scanf("%d%d%d",&N,&S,&K)!=EOF) 85 { 86 init(); 87 for(int i=1;i<N;i++) 88 { 89 scanf("%d%d%d",&a,&b,&val); 90 add(a,b,val); 91 } 92 dfs(S,-1); 93 printf("%d\n",dp[S][K]); 94 } 95 return 0; 96 }
标签:
原文地址:http://www.cnblogs.com/cnblogs321114287/p/4329133.html