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 }