DP 樹形DP luogu2015 二叉蘋果樹

2021-09-29 22:49:27 字數 2607 閱讀 6291

一棵二叉蘋果樹,上結了蘋果需要砍去一些邊,求保留q條邊時最多能保留多少蘋果。(1<=n,q<=100)

2   5

\ /

3 4

\ /1

題目保證了原始蘋果樹有分叉則必為二叉,且1為root注意輸入時父子順序是不確定的,所以需要做處理

定義d pi

,j

dp_dp

i,j​

表示編號為i的子樹在保留j條邊的情況下獲得的最大蘋果數目,則狀態轉移為

d pi

,j=m

ax

dpi,j​

表示樹i最多保留j條邊時的最大蘋果總數,此時不存在問題(與另一種做法不同)

關於遍歷順序的問題,一般採用dfs回溯時做dp;為防止爆棧,也可以使用bfs,然後逆序遍歷

一開始,我採用了另外一種dp思路,定義dpi

,j

dp_dp

i,j​

為樹i砍去j條邊的最大蘋果總數。簡單地看,這樣也沒什麼不妥,並且狀態轉移與保留dp差異不大,但是這樣dp存在以下神坑

必須保證砍去的邊j總是小於樹i的總邊數,而不能出現虛擬砍伐。比如,樹i(5邊)總共砍5刀,左樹lc(4邊),右樹rc(1邊),如果給分配成右樹砍4刀,左數砍1刀,則在事實上只是砍了2刀。這樣的錯誤主要來自於錯誤的dp狀態定義,在這之前,我的dp狀態定義是樹i最多砍j刀的最大蘋果數目。顯然,不砍時最優,故最多砍j刀的最大數相當於砍0刀的最大數。當把樹i的左邊砍掉時,也就意味著整個左子樹都被一定砍掉了,此時右子樹需砍伐j - (cnt[lc] + 1) - 1條邊。這裡還有乙個誤區在於,雖然主觀上只砍去1條邊,給人感覺右子樹還要砍j - 1 ;或者是砍去1條邊,左子樹上的cnt條邊還可以選擇性地砍伐k條,造成右半部分可以對應地砍伐j - (1 + k)條邊。但這兩種想法都是錯的,是把砍邊當成了機會而非事實,正確的想法是 砍去1條左子邊,就造成了整個左半部分被去除的事實,即樹失去了cnt[lc] + 1條邊。因為我們最終要的結果是保留多少條邊,所以砍去1條主邊和砍去左半部分所有邊造成的結果都是一樣的。

基於以上神坑,所以極不推薦那種做法!

#include

#include

#include

#include

using

namespace std;

const

int maxn =

110;

const

bool dbg =

false

;int n,q;

vector<

int> son[maxn]

;int father[maxn];;

int que[maxn]

, front, back;

int dp[maxn]

[maxn]

;int cnt[maxn]

;int

main()

//bfs排序

que[back++]=

1;while

(back!= n)

//統計每棵子樹的枝幹總數(邊數)

for(

int i=n-

1;i>=

0;i--

)//從葉子按順序dp

while

(back)

if(cnt[lc]

>=

(j -1)

&& j >=1)

temp =

max(temp, dp[lc]

[j-1])

;if(cnt[rc]

>=

(j-1

)&& j >=1)

temp =

max(temp, dp[rc]

[j-1])

;if(dbg)

printf

("\n");

dp[i]

[j]= temp;}}

}//輸出結果

printf

("%d\n"

, dp[1]

[q])

;return0;

}

DP 樹形DP luogu2014 選課

學生要在n門課程中選m門課程,每門課程最多依賴於一門前置課程 可以有多門課程沒有前置課程 問能獲得的最大學分是多少。1 m n 300 顯然,每門課程依賴至多一門,有課程可以沒有依賴,所以這是乙個多叉樹森林。森林不太好處理,所以我們可以給森林加個虛擬根節點 0,讓每棵樹的根節點連到這個總結點上。問題...

樹形DP 模版題 p2015

狀態轉移方程也就顯而易見了 f u i max f u i f u i j 1 f v j e i w 1 i min q,sz u 0 j min sz v i 1 u表示當前節點,v是u的乙個子節點,sz u 表示u的子樹上的邊數,q就是題目中要求的最多保留邊數 include include ...

HAOI2015 樹上染色(樹形dp)

有一棵點數為 n 的樹,樹邊有邊權。給你乙個在 0 n 之內的正整數 k 你要在這棵樹中選擇 k個點,將其染成黑色,並將其他 的n k個點染成白色 將所有點染色後,你會獲得黑點兩兩之間的距離加上白點兩兩之間的距離的和的受益。問受益最大值是多少。輸入格式 第一行包含兩個整數 n,k 接下來 n 1 行...