URAL 1018. Binary Apple Tree(树形DP)
第一个树形DP,这个题,以前用普通方法搞,WA了,然后知道是树形DP后,以为类似是数塔只不过是在树上而已,原来理解错了。。。参考了很多的解题报告,看了很多关于树形DP的文档。。终于,完成了,感觉非常类似滑雪的记忆化搜索。
状态转移分情况讨论一下,有和一个叉连接,和两个叉连接。节点数总是m+1的。
1 #include <stdio.h> 2 #include <string.h> 3 struct tree 4 { 5 int l,r; 6 }p[101]; 7 int o[101][101],key[101],n,m; 8 int map[101][101]; 9 void build(int x)//建树 10 { 11 int i,j = 1; 12 for(i = 1;i <= n;i ++) 13 { 14 if(!key[i]&&o[x][i]) 15 { 16 if(j == 1) 17 { 18 p[x].l = i; 19 j ++; 20 } 21 else if(j == 2) 22 { 23 p[x].r = i; 24 j ++; 25 } 26 key[i] = 1; 27 build(i);//递归建树 28 } 29 } 30 } 31 int dp(int i,int j) 32 { 33 int a,ll,rr; 34 if(map[i][j] >= 0)//不要重复计算 35 return map[i][j]; 36 if(i == 0||j == 0)//如果节点数为0或者子树为空 37 { 38 map[i][j] = 0; 39 return map[i][j]; 40 } 41 map[i][j] = dp(p[i].l,j-1)+o[i][p[i].l];//只和左子树相连 42 if(map[i][j] < dp(p[i].r,j-1)+o[i][p[i].r])//只和右子树相连 43 map[i][j] = dp(p[i].r,j-1)+o[i][p[i].r]; 44 for(a = 0;a <= j-2;a ++)//讨论和两个子树都相连还剩下j-2个节点 45 { 46 ll = dp(p[i].l,a) + o[i][p[i].l]; 47 rr = dp(p[i].r,j-a-2) +o[i][p[i].r]; 48 if(map[i][j] < ll + rr) 49 map[i][j] = ll + rr; 50 } 51 return map[i][j]; 52 } 53 int main() 54 { 55 int i,sv,ev,w; 56 scanf("%d%d",&n,&m); 57 for(i = 1;i <= n-1;i ++) 58 { 59 scanf("%d%d%d",&sv,&ev,&w); 60 o[sv][ev] = w; 61 o[ev][sv] = w; 62 } 63 memset(map,-1,sizeof(map)); 64 key[1] = 1; 65 build(1); 66 printf("%d\n",dp(1,m)); 67 return 0; 68 }