NOIP2003 加分二叉樹 dp 區間型動態規劃

2021-07-15 14:59:26 字數 1298 閱讀 4729

設乙個n個節點的二叉樹tree的中序遍歷為(l,2,3,…,n),其中數字1,2,3,…,n為節點編號。每個節點都有乙個分數(均為正整數),記第i個節點的分數為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

5 7 1 2 10

145

3 1 2 4 5

每個測試點1s

解題思路

題目已經給出了中序遍歷,對於樹結構,只要確定了根,就好辦多了。於是我們列舉根節點,用f[i,j]表示i....j的最優加分,就有f[i,j]=max(i<=k<=j)   g[i,j]=a[k];(當f[i,j]更新時更新g[i,j])對於方案的記錄,也應該是對應最優值求解時隨著狀態轉移而確定下來的,所以相應也應該是乙個二維的。輸出的時候就遞迴輸出,判斷一下是不是最後乙個就好了。

**

#include#includeusing namespace std;

long long f[40][40];//從i到j,兩個端點得到的最大值

int g[40][40];//從i到j,選哪個做根節點

long long a[40];

int sum=1;

int n;

//先序輸出

void print(int l,int r)

int main()

for(int len=2;len<=n;++len)//不管i,j表示什麼含義,最外層迴圈一定是列舉長度

else if (f[i][i]+f[i+1][j] < f[i][j-1]+f[j][j])//沒有右兒子

//左右兒子都有

for(k=i+1;k<=j-1;++k)

{if(f[i][j]

noip 2003 加分二叉樹(DP)

題目鏈結 思路 用乙個二維陣列dp i,j 表示中序遍歷中從 i 到 j 的區間組成的子樹的集合,dp i,j 的值表示這些子樹中得分的最大值,轉移方程很簡單,dp i,j max dp i,j dp i,k 1 dp k 1,r 需要遍歷 i 到 j 的每乙個點,判斷哪乙個是根節點,然後根據根節點...

NOIP 2003 加分二叉樹

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

NOIP 2003 加分二叉樹

評測傳送 這個題可以記憶化搜尋做的。注意邊界條件。對於先序遍歷,遞迴就可以了 在dfs的時候用乙個陣列記錄根節點就可以了 include include include include include include define ll long long using namespace std i...