C++ 史上最详细的树形DP

看了很多的博客,基本上关于树形DP是一句话带过:说什么孩子节点选或者不选,父节点选和不选。对于初学者来说,我个人觉得他们的内心需要一些具象的表达方法,说白点,就是详细点,直接一点可以上图说明。

我们就不来什么具体题目了,直接画个图:

假设要求:选取某个节点的时候,就不能选取它的父亲节点和孩子节点,求选取节点数量最大是什么?

比如你选择了节点 3,那么你不能选取1 和 5,想必大家可能接触过《没有上司的舞会》那道题,对,这就是那道题的原型。

 但是还得说个重点:我们先要从叶子节点算起,通俗点讲,符合DFS的特点。

我们声明f [ i ][ 0 ] =0 表示 i 没有选取价值,f[ i ][ 1 ]=1表示 i 选取的价值

首先第一步:

假设节点  1 选取:f [ 1 ][ 1 ] = 1;

假设节点 1 没选取:f [ 1 ][ 0 ] =0;

回退到节点 3:

假设节点  3 选取,那么孩子节点就不能选取了,对吧:f [ 3 ][ 1 ] += f [ 孩子节点 ][0];

假设节点 3 没选取,那么孩子节点可以选择也可以不选择,我们选取其中最大值就行,这个时候大家可能有点糊涂,有的甚至在想选取了不更好吗?您接着看,过会就明白了:f [ 3 ][ 0 ] += max( f [ 孩子节点 ][0], f [ 孩子节点 ][1]);

通过一番这样的设想后,我们得出:f[3][0]=2,f[3][1]=1;

 

现在我们直接跳到根节点