zoukankan      html  css  js  c++  java
  • 树形DP学习笔记

    1.为什么会有树形DP

         正常来说,线性DP用来解决序列的问题,但是当我们维护的数据结构发生变化的时候,比如,现在我们需要对一棵树

    进行DP,普通的线性DP边无法解决了,这个时候,就需要用到树形DP了

    2.树形DP的应用场景

        1中的应用场景给的比较抽象,这里详细的来说一下。最经典的例子就是一个等级森严的公司召开会议,在这个公司里,

    每个人都有一个对应的上司,而终极大BOSS老板则没有上级。如果一个人的直接上级(就是相当于他的父节点)出席会议

    的话,那他一定不会出席。现在,问你如果有n个人缺席,那么最多有多少人出席。

       即:树形DP应用于存在依赖关系的数据结构中求最优解的问题。

    3.典型例题理解算法

       传送门

    题目描述

    有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)

    这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。

    我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树

    2   5
      / 
      3   4
        /
        1
    

    现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。

    给定需要保留的树枝数量,求出最多能留住多少苹果。

    输入格式

    第1行2个数,N和Q(1<=Q<= N,1<N<=100)。

    N表示树的结点数,Q表示要保留的树枝数量。接下来N-1行描述树枝的信息。

    每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。

    每根树枝上的苹果不超过30000个。

    输出格式

    一个数,最多能留住的苹果的数量。

    输入输出样例
    Input #1
    5 2
    1 3 1
    1 4 10
    2 3 20
    3 5 20
    Output #1

    21

    这道题是一个典型的入门题,很经典吖。
    直接在代码里讲啦QWQ
    看代码之前最好先想一下,特别是细节,里面有几个地方很容易出错
    码风还好不用担心:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<algorithm>
     6 #include<cmath>
     7 #define N 1000
     8 
     9 using namespace std;
    10 
    11 struct Node{
    12     int u;
    13     int v;
    14     int val;
    15     int last;
    16 }edge[N];
    17 
    18 int head[N]={false},siz[N]={false},cnt_edge=0,n,q;
    19 int f[N][N]={0};
    20 
    21 inline int Read()
    22 {
    23     int num=0,k=1;
    24     char c=getchar();
    25     while(c!='-'&&(c>'9'||c<'0')) c=getchar();
    26     if(c=='-') {k=-1;c=getchar();}
    27     while(c>='0'&&c<='9'){num=(num<<1)+(num<<3)+(c^48);c=getchar();}
    28     return num*k;
    29  } 
    30  
    31 inline void add_edge(int u,int v,int val)
    32 {
    33     edge[++cnt_edge].u=u;
    34     edge[cnt_edge].v=v;
    35     edge[cnt_edge].val=val;
    36     edge[cnt_edge].last=head[u];
    37     head[u]=cnt_edge;
    38 }
    39 
    40 inline void TDP(int u,int fa)
    41 {
    42     for(int i=head[u];~i;i=edge[i].last)//~i的意思是i!=-1 
    43     {
    44         int v=edge[i].v;
    45         if(v==fa) continue;
    46         TDP(v,u);siz[u]+= siz[v]+1;//要加上连到自己的边 
    47         for(int j=min(siz[u],q);j;j--)//01Bag Problem
    48         {
    49             for(int k=min(j-1,siz[v]);k>=0;k--)//允许其儿子为叶子节点 
    50             {
    51                 f[u][j]=max(f[u][j],f[u][j-k-1]+f[v][k]+edge[i].val);
    52         
    53             }
    54         }
    55     }
    56 }
    57 
    58 int main ()
    59 {
    60     memset(head,-1,sizeof(head));
    61     n=Read();q=Read();
    62     for(int i=1;i<n;i++)
    63     {
    64         int u=Read();int v=Read();int w=Read();
    65         add_edge(u,v,w);add_edge(v,u,w);
    66     }
    67     TDP(1,-1);
    68     printf("%d
    ",f[1][q]);
    69     return 0;
    70 }
    View Code
  • 相关阅读:
    cvCreateStructuringElementEx理解
    GNU_GSL相关
    粒子滤波(转)
    C++指针拷贝
    c++中的复制构造函数
    通过几道题目找自信
    C++网络编程基础
    linux system : install flash player
    ContentType一览
    O_RDWR O_CREAT等open函数标志位在哪里定义?(格式还要编译,答案在最后一段)
  • 原文地址:https://www.cnblogs.com/Roysblog/p/14050506.html
Copyright © 2011-2022 走看看