洛谷 P2014 選課 樹形DP之一

2021-10-23 00:21:56 字數 1314 閱讀 7181

![在這裡插入描述](

這是一道樹形dp的題,它的特點在於選課的數目有上限,且一定得按樹的關係生成,這與揹包問題不大相同,這道dp思想關鍵之處就是通過能否找到這樣乙個關係,可以很好的描述子問題之間的聯絡,我們設f[i][j]為以第i個點為根結點,有j門課可以選,這個情況下的最大學分。

那麼對於每乙個節點i,它的各個j是由所有子節點共同決定的,因為對於i它可以拿任意個子節點,反正只要得到f[i][j]的最大值就好了,那麼如何處理這些子節點才可以得到f[i][j]呢,一開始我想第乙個節點拿x1門,第二個節點拿x2門。。。

最後x1+x2+…=j-1,(剩下的1給父節點)就好了,可這樣很難表示,如何表示才能完整的描述所有情況?

類似完全揹包處理多個物體的情況,我們只需要每個子節點重新走過上乙個子節點的情況就好了,也就是說一開始先認為只有乙個子節點,設為 v,那麼有狀態轉移方程

f[i][j]=max(f[i][j],f[v][k]+f[i][j-k]),k表示v節點及它後面的樹中一共拿k門課所能得到的最大的學分,這樣我們就有了第乙個子節點的狀態,此後對於所有的子節點我們都用這乙個方程,這樣所有的子節點的狀態都可以整合在f[i][j]中了。

細節的解釋:

當遍歷到新的節點狀態,那麼f[i][j]是我們要算的節點狀態,f[i][j-k]目前存的還是上乙個子節點的狀態,這樣就可以實現所有 「子節點的取值情況的遍歷取最大值」 這一目標

為了實現這一目標我們必須對j按從大到小遍歷,其它不做要求

使用遞迴時注意邊界處理

原題本是乙個森林,我們虛擬出乙個0節點,並把它計入到課程的數目中(為了統一情況)

所以最後的結果是f[0][m+1]

**如下:

#include

#include

using

namespace std;

int n,m;

vector<

int>g[

301]

;//鄰接表

int w[

301]

;//權值

int f[

301]

[301];

void

dfs(

int no)

//父節點位置

}for

(int i=

1;i<=m+

1;i++

)//最後的所有結果加上父節點它本身的學分

f[no]

[i]+

=w[no];}

intmain()

dfs(0)

; cout<[m+1];

return0;

}

洛谷P2014 選課 樹形dp

給出n 300 n leq300 n 30 0個結點,每個結點都有乙個權值,然後一些結點必須只有選了前驅結點這個結點才可以被選。現在最多選m 300 m leq300 m 30 0個結點,求最大權值。實際上這個是乙個森林,但是通過設定乙個權值為0 00的虛點0 00,把所有的沒有前驅的點全部連到這個...

洛谷P2014 選課(樹形DP)

傳送門 難度提高 省選 該題是一道經典的樹形dp題目,基本就是樹形dp的板子題。注意點的解釋參考 為什麼最後兩行要單獨拿出來做呢?for int i s x i 0 i f x i 1 f x i p x 我們回到題面上,父親是兒子的先修課,所以沒有父親時,兒子再多也沒有用,揹包中處理的子樹是不帶根...

洛谷P2014 選課 樹形dp

在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有n門功課,每門課有個學分,每門課有一門或沒有直接先修課 若課程a是課程b的先修課即只有學完了課程a,才能學習課程b 乙個學生要從這些課程裡選擇m門...