設乙個 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...