HDU-4003 Find Metal Mineral 树形DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4003
状态转移方程还是很好想的:f[i][j]表示第 i 个节点放 j 个机器人的最优解,f[i][j]=Min{ f[i][j] , f[i][j-k] + f[v][k] + (k?k:2)*e[i].w } 。
写这个树形DP的时候,暴露了我以前没有仔细考虑的问题,导致状态转移的时候删删改改了很久。、
1.仔细考虑转移方程初始化的问题,要根据求Min或者Max以及容量是否恰好来确定。
2.在分组背包转移时,f[i][j]是前几组的最优值。
1 //STATUS:C++_AC_256MS_1084KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vector> 10 #include<queue> 11 #include<stack> 12 #include<map> 13 using namespace std; 14 #define LL __int64 15 #define pii pair<int,int> 16 #define Max(a,b) ((a)>(b)?(a):(b)) 17 #define Min(a,b) ((a)<(b)?(a):(b)) 18 #define mem(a,b) memset(a,b,sizeof(a)) 19 #define lson l,mid,rt<<1 20 #define rson mid+1,r,rt<<1|1 21 const int N=10010,INF=0x3f3f3f3f,MOD=10000,STA=8000010; 22 const double DNF=1e13; 23 24 struct Node{ 25 int u,v,w; 26 }e[N*2]; 27 28 int first[N],next[N*2],vis[N],f[N][11]; 29 int n,s,k,mt; 30 31 void adde(int a,int b,int c) 32 { 33 e[mt].u=a;e[mt].v=b; 34 e[mt].w=c; 35 next[mt]=first[a];first[a]=mt++; 36 e[mt].u=b;e[mt].v=a; 37 e[mt].w=c; 38 next[mt]=first[b];first[b]=mt++; 39 } 40 41 void dfs(int u) 42 { 43 int i,j,v,q; 44 i=first[u]; 45 vis[u]=1; 46 if((next[i]==-1 || i==-1) && u!=s){ 47 f[u][0]=f[u][1]=0; 48 return; 49 } 50 f[u][0]=0; 51 for(;i!=-1;i=next[i]){ 52 v=e[i].v; 53 if(vis[v])continue; 54 dfs(v); 55 for(j=k;j>=1;j--){ 56 f[u][j]+=f[v][0]+2*e[i].w; 57 for(q=1;q<=j;q++) 58 f[u][j]=Min(f[u][j],f[u][j-q]+f[v][q]+q*e[i].w); 59 } 60 f[u][0]+=f[v][0]+2*e[i].w; 61 } 62 } 63 64 int main() 65 { 66 // freopen("in.txt","r",stdin); 67 int i,x,y,w; 68 while(~scanf("%d%d%d",&n,&s,&k)) 69 { 70 mt=0; 71 mem(vis,0); 72 mem(f,0); 73 mem(first,-1); 74 for(i=1;i<n;i++){ 75 scanf("%d%d%d",&x,&y,&w); 76 adde(x,y,w); 77 } 78 79 dfs(s); 80 81 printf("%d\n",f[s][k]); 82 } 83 return 0; 84 }