動態規劃(7) 樹形DP

2021-10-02 18:24:44 字數 1837 閱讀 7854

昨天本來就能寫的,結果寫了倆個題寫了四五個小時,於是乎拖到今天了。

這個題就很好寫了,不像狀態壓縮,真的是難理解…大佬部落格

f[u][0]表示從以u為根節點,不選u的方案。

f[u][1]表示從以u為根節點,選u的方案。

所以f[u][0] = ∑max(f[si][0],f[si][1])i是遍歷下一層的子節點

f[u][0] = ∑f[si][0] i是遍歷下一層的子節點

#include

using

namespace std;

const

int n=

6010;;

int f[n][2

];int h[n]

,e[n]

,ne[n]

,idx;

bool st[n]

;int n;

vector<

int> ve[n]

;void

dfs(

int u)

}int

main()

int root=1;

while

(st[root]

) root++

;//求取根節點

dfs(root)

; cout<<

max(f[root][0

],f[root][1

])

}

其實更下面喜歡這樣寫…感覺舒服多了…

如果是線型的一串一維陣列的話 不能選擇相鄰的數字 要讓選擇的數的和最大

那麼就有遞推方程dp[i] = max(dp[i-1],dp[i-2] + a[i])

max裡面前乙個式子代表我不選a[i] 那麼就能從dp[i-1] 轉移過來

後面乙個代表我選了這個 那麼就是從dp[i-2] + a[i] 轉移過來

兩者取最大值就是我們需要的答案 那麼這題的話就可以用這個思想

如果我們選擇了這個節點的值的話 我們就只能從這個節點出發的下下一層轉移了 下一層不能選了

如果我們不選這個節點 我們直接從下一層節點轉移就好了 兩者取最大值 附:大佬部落格

#include

using

namespace std;

const

int maxn =

6010

;int val[maxn]

, in[maxn]

;int dp[maxn]=;

// 記憶化優化 相當於剪枝了

vector<

int> g[maxn]

;// 記錄樹

intdfs

(int root)

ans1 +

=dfs

(g[root]

[i])

;// 我不選這個就可以直接從這一層轉移

tans =

max(ans1,ans)

;// 兩者取一下最大值

}return dp[root]

= tans;

// 記憶化 避免很多的多餘運算

}int

main()

int u,v;

while

(cin>>u>>v&&u!=0)

int root , ans =0;

for(

int i =

1; i <= n; i++

) ans =

dfs(root)

; cout<}

怎麼說呢,這幾天寫dp寫的真的是心累,智商低的人的苦你們是不會理解的…未來三天寫不寫dp了,準備惡補數學知識三天.

動態規劃 樹形DP

樹形dp,即在樹上進行的動態規劃,由於樹固有的遞迴性質,因此樹形dp往往也遞迴進行。某大學有 n nn 個職員,編號為 1.n1.n 1.n 他們之間有從屬關係,也就是說他們的關係就像一棵以校長為根的樹,父結點就是子結點的直接上司。現在有個周年慶宴會,宴會每邀請來乙個職員都會增加一定的快樂指數 r ...

( 動態規劃專題 ) 樹形dp

動態規劃專題 樹形dp 直接看例題 p2015 二叉蘋果樹 有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3...

動態規劃二(樹形DP)

顧名思義,是指將dp建立在樹狀結構的基礎上。問題描述 有一棵 n 個節點的樹,樹上每個節點都有乙個正整數權值。如果乙個點被選擇了,那麼在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?輸入格式 第一行包含乙個整數 n 接下來的一行包含 n 個正整數,第 i 個正整數代表點 i 的權值。接...