有一棵蘋果樹,如果樹枝有分叉,一定是分2叉(就是說沒有只有1個兒子的結點)
這棵樹共有n個結點(葉子點或者樹枝分叉點),編號為1-n,樹根編號一定是1。
我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹
現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果。2
5 \ /34
\ /1
給定需要保留的樹枝數量,求出最多能留住多少蘋果。
第1行2個數,n和q(1<=q<= n,1
乙個數,最多能留住的蘋果的數量。
521
3114
102320
3520
21
解題思路
這是一道樹形dp的板子題。
f[i][j]表示以i為根節點的子樹,保留j條樹枝時的,保留的最大蘋果數。
(這道題有乙個隱含的條件,當某條邊被保留下來時,從根節點到這條邊的路徑上的所有邊也都必須保留下來)那麼狀態轉移方程為:
f [d
ep][
j]=m
ax(f
[dep
][j]
,f[s
on][
k]+f
[dep
][j−
k−1]
+a[s
on][
dep]
);
f[dep][j]=max(f[dep][j],f[son][k]+f[dep][j−k−1]+a[son][dep]);
f[dep]
[j]=
max(
f[de
p][j
],f[
son]
[k]+
f[de
p][j
−k−1
]+a[
son]
[dep
]);為什麼是f[d
ep][
i−k−
1]
f[dep][i−k−1]
f[dep]
[i−k
−1]而不是f[d
ep][
i−k]
f[dep][i−k]
f[dep]
[i−k
]?因為保留一條邊必須保留從根節點到這條邊路徑上的所有邊,那麼如果你想從u的子節點v的子樹上留邊的話,也要留下u,v之間的連邊。
另外,我的連線方式有點特別,用的是鄰接表連線點,用鄰接矩陣存邊權。其實只用鄰接矩陣就可以了,比較方便。
#include
#include
#include
#include
using
namespace std;
int n,q,x,y,v,tot,h[
101]
,e[101
],f[
101]
[101
],s[
101]
[101];
struct node
a[220];
void
add(
int x,
int y)
; h[x]
=tot;
}voiddp(
int k)}}
}int
main()
dp(1)
; cout<[q];
//q是要保留的樹枝數量
return0;
}
洛谷 P2015 二叉蘋果樹 樹形dp
有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3 4 1現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋...
洛谷P2015 二叉蘋果樹(樹形dp)
有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3 4 1現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋...
洛谷P2015 二叉蘋果樹 樹形dp)
題目描述 有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 34 1現在這顆樹枝條太多了,需要剪枝。但是一些樹枝...