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 }

 

posted @ 2012-07-27 16:03  Naix_x  阅读(217)  评论(0编辑  收藏  举报