動態規劃 習題 蘋果二叉樹 二維樹形DP

2021-09-11 07:11:16 字數 2038 閱讀 5105

題目描述

有一棵蘋果樹,如果樹枝有分叉,一定是分2叉(就是說沒有只有1個兒子的結點)。這棵樹共有n個結點(葉子點或者樹枝分叉點),編號為1-n,樹根編號一定是1。 我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹:

2 53 4

現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果。 給定需要保留的樹枝數量,求出最多能留住多少蘋果。

輸入格式

第1行2個數,n和q(1<=q<= n,1輸出格式

乙個數,最多能留住的蘋果的數量。

這道題就是一道典型的二維樹形dp問題。

設f [i

][j]

f[i][j]

f[i][j

]表示在以i

ii為根的子樹中,保留了j

jj個枝條所保留的最大蘋果。

狀態轉移方程:f[x

][i]

=max

(f[y

][j]

+val

(x,y

)+f[

x][i

−j−1

]),y

∈son

(i

)f[x][i]=max(f[y][j]+val(x,y)+f[x][i-j-1]),\ y∈son(i)

f[x][i

]=ma

x(f[

y][j

]+va

l(x,

y)+f

[x][

i−j−

1]),

y∈so

n(i)

相信狀態轉移方程十分清楚明白,這裡的f[x

][i−

j−1]

f[x][i-j-1]

f[x][i

−j−1

]顯然是先前已經列舉過的其它子樹。

我們此時需要求出i和j的取值範圍,通過仔細畫圖可以得知:

1 ≤i

≤min

(siz

e[x]

−1,q

)1≤i≤min(size[x]-1,q)

1≤i≤mi

n(si

ze[x

]−1,

q)0 ≤j

≤min

(siz

e[y]

−1,i

−1

)0≤j≤min(size[y]-1,i-1)

0≤j≤mi

n(si

ze[y

]−1,

i−1)

注意狀態轉移方程i

ii和j

jj需要逆序列舉,原理同01揹包

01揹包

01揹包

,f [x

][i−

j−1]

f[x][i-j-1]

f[x][i

−j−1

]是同一棵子樹的轉移。

**如下:

#include

#define mp make_pair

using

namespace std;

int n,q;

int size[

200]

;vector< pair<

int,

int>

>a[

200]

;int f[

200]

[200];

void

getsize

(int x,

int fa)

}voiddp(

int x,

int fa)

}int

main

(void

)getsize(1

,0);

dp(1,

0);printf

("%d"

,f[1

][q]);

return0;

}

藍橋杯訓練 動態規劃 蘋果二叉樹

問題描述 二叉蘋果樹 題目描述 有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3 4 1 現在這顆樹枝條太多...

樹形dp ural1018蘋果二叉樹

include include include include include include define maxn 200 define inf 0xfffffff using namespace std int dp maxn maxn dp i j 表示以i為根取j條樹枝的最大值 1.只有乙...

二叉樹習題之重建二叉樹

對於給定前序和中序的重建方法。1 前序的第乙個元素一定是樹的根節點,在中序集合中找到此元素,那麼該元素的左面即為根的左子樹,右面為右子樹。2 找到前序的第二個元素,重複上面的步驟。自寫程式的效率大概為 n n 2 或最大的那個元素 這點很坑,斟酌改掉 目前沒發現更快的寫法 自己寫 結果以連續記憶體的...