動態規劃加分二叉樹問題

2021-10-24 11:58:02 字數 1672 閱讀 8705

設乙個 n個節點的二叉樹tree 的中序遍歷為(1,2,3,…,n),其中數字 1,2,3,…,n 為節點編號。每個節點都有乙個分數(均為正整數),記第 ii 個節點的分數為 di,tree 及它的每個子樹都有乙個加分,任一棵子樹 subtree(也包含 tree 本身)的加分計算方法如下:

subtree 的左子樹的加分 x subtree 的右子樹的加分 + subtree 的根的分數。

若某個子樹為空,規定其加分為 1,葉子的加分就是葉節點本身的分數。不考慮它的空子樹。

試求一棵符合中序遍歷為 (1,2,3,…,n) 且加分最高的二叉樹 tree。要求輸出

tree 的最高加分。

tree 的前序遍歷。

第 1 行 1個整數 n,為節點個數。

第 2 行 n個用空格隔開的整數,為每個節點的分數

第 1行 1 個整數,為最高加分(ans≤4,000,000,000)。

第 2 行 n個用空格隔開的整數,為該樹的前序遍歷。

輸入 #1

5

5 7 1 2 10

輸出 #1

145

3 1 2 4 5

n

<30。

分數 <100。

根據得分的計算方法,我們可以知道要想分數最大,就要讓左子樹和右子樹分數最大,而左子樹和右子樹又需要他們的左子樹和右子樹分數最大,所以這道題可以用動態規劃來做。

root[i][j]表示從節點i到節點j組成的二叉樹的根節點

f[i][j]表示從節點i到節點j組成的二叉樹所能得到的最大分數

那麼狀態轉移方程就是f[i][j]=max(f[i][j],f[i][k-1]*f[k+1][j]+f[k][k]),表示以k為根節點會不會使分數更高

目標狀態是f[1][n]

至於輸出前序遍歷,就是遞迴不斷輸出根節點,詳見**

#include

using

namespace std;

int n;

int a[30]

;int root[30]

[30];

//root[i][j]表示從節點 i到節點 j這段樹的根節點

int f[30]

[30];

//f[i][j]表示從節點 i到節點 j這段樹能得到的最大分數

void

out(

int l,

int r)

//遞迴輸出前序遍歷

cout<[r]<<

" ";

out(l,root[l]

[r]-1)

;//繼續左子樹

out(root[l]

[r]+

1,r)

;//繼續右子樹

}intdp(

)//動歸找最大分數 }}

}}intmain()

for(

int i=

1;i<=n;i++)dp

(); cout<[n]

1,n)

;return0;

}

加分二叉樹(區間動態規劃)

設乙個n個節點的二叉樹tree的中序遍歷為 l,2,3,n 其中數字1,2,3,n為節點編號。每個節點都有乙個分數 均為正整數 記第j個節點的分數為di,tree及它的每個子樹都有乙個加分,任一棵子樹subtree 也包含tree本身 的加分計算方法如下 subtree的左子樹的加分 subtree...

加分二叉樹

描述 設乙個n個節點的二叉樹tree的中序遍歷為 l,2,3,n 其中數字1,2,3,n為節點編號。每個節點都有乙個分數 均為正整數 記第i個節點的分數為di,tree及它的每個子樹都有乙個加分,任一棵子樹subtree 也包含tree本身 的加分計算方法如下 subtree的左子樹的加分 subt...

加分二叉樹

設乙個n個節點的二叉樹tree的中序遍歷為 l,2,3,n 其中數字1,2,3,n為節點編號。每個節點都有乙個分數 均為正整數 記第i個節點的分數為di,tree及它的每個子樹都有乙個加分,任一棵子樹subtree 也包含tree本身 的加分計算方法如下 subtree的左子樹的加分 subtree...