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 }

 

你可能感兴趣的:(binary)