前言
最近做了些树形DP的基础题目,不是特别难,最难的是道紫题……
然后为了让自己以后更好地回忆,也是现在地一种梳理,所以我还是点开了“创作中心”,开始总结。
目录
首先,个人感觉树形DP题目常见的两大类,一种是关乎子树的,一种是背包。
感觉其一更好打一些,不过也不是没有难题。
背包的话,就是注意细节,将树上的DP慢慢推导成普通的几种背包即可。
子树类
以下来几道子树类的例题,一边记录,一边讲解总结。
没有上司的晚会
说到子树类的DP,就不得不说树形DP入门题,“没有上司的晚会”
这道题的感觉给人焕然一新的感觉。(因为这是我第一次接触树形DP
我们可以将上下属的关系转化成一棵树:上属就是下属的父节点,这样就可以构成一棵简单的关系树了。
题目的解法也是很简单:我们只需要设 f i , 0 f_{i,0} fi,0为第i个人不去晚会的最大快乐值,反之 f i , 1 f_{i,1} fi,1为第i个人参加晚会的最大快乐值。然后在递归便利这棵树中实现,最终的答案就是 m a x ( f r o o t , 0 , f r o o t , 1 ) max(f_{root,0},f_{root,1}) max(froot,0,froot,1),其中(root为这棵树的根节点
所以,我们可以知道,根据题目描述:
一个人去,那他的下属就不能去。
一个人不去,那他的下属可以不去也可以去。
所以转移方程显而易见(其中 s o n i , j son_{i,j} soni,j表示i的第j个儿子:
f i , 0 f_{i,0} fi,0+= m a x ( f s o n i , j , 0 , f s o n i , j , 1 ) max(f_{son_{i,j},0},f_{son_{i,j},1}) max(fsoni,j,0,fsoni,j,1)
f i , 1 f_{i,1} fi,1+= f s o n i , j , 0 f_{son_{i,j},0} fsoni,j,0
CODE
#include<bits/stdc++.h>
using namespace std;
int n,x[6005],son[6005][6005],f[6005][2],p,q,root;
bool bz[6005];
int max(int a,int b)
{
if(a>b) return a;
else return b;
}