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;

 

現在我們直接跳到根節點