加分二叉樹 樹型DP

2021-05-22 21:08:46 字數 1300 閱讀 7134

題目:

設乙個n個節點的二叉樹tree的中序遍歷為(l,2,3,…,n),其中數字1,2,3,…,n為節點編號。每個節點都有乙個分數(均為正整數),

記第j個節點的分數為di,tree及它的每個子樹都有乙個加分,任一棵子樹subtree(也包含tree本身)的加分計算方法如下:

subtree的左子樹的加分× subtree的右子樹的加分+subtree的根的分數

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

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

(1)tree的最高加分

(2)tree的前序遍歷

輸入格式

第1行:乙個整數n(n<30),為節點個數。

第2行:n個用空格隔開的整數,為每個節點的分數(分數<100)。

輸出格式

第1行:乙個整數,為最高加分(結果不會超過4,000,000,000)。

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

樣例輸入

5 7 1 2 10

樣例輸出

3 1 2 4 5

注意:例題的前序輸出 其實 3 2 1 5 4也是可以的

有多顆同樣分數的樹

為了在**上通過  應該「盡量往右偏」即從右邊開始判斷 

這一題狀態的表示是關鍵,因為輸入的是一顆樹的中序遍歷,所以樹就不是隨便亂建的了。

中序數遍歷有乙個特點

就是把這顆樹的一顆子樹拿出來,在這顆樹中序輸出的時候,這顆子樹的節點是連在一起輸出的。

那麼我們用f[i][j]表示節點i到j得子樹,我們最後要得到的就是f[1][n]

f[i][j] = max  i <= n <= j  如果f[a][b],a > b 那麼 f[a][b] = 1  初始: f[i][i] = s[i]

求出了最大值,本題還有乙個問題,要先序遍歷。所以我們要儲存每一顆子樹的根

這就不難了 每次在做f[i][j]的時候  root[i][j] = n(f[i][j]最大的那個)

先序輸出我用了乙個遞迴

void _fprint( int begin,int end )

int k = root[begin][end];

cout << k << ' ';

if( k-1 >= begin )

_fprint( begin,k-1 );

if( k+1 <= end )

_fprint( k+1,end );

完整**:

樹型DP 加分二叉樹

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

區間DP 加分二叉樹

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

加分二叉樹

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