noip 2003 加分二叉樹(DP)

2021-09-26 07:49:51 字數 961 閱讀 2076

題目鏈結

思路:用乙個二維陣列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 的每乙個點,判斷哪乙個是根節點,然後根據根節點把樹再次分為左右子樹

注意計算順序,為了保證計算當前值的時候需要用到的值已經被計算過了,需要對區間的長度進行遍歷,區間長度從短到長計算,其次遍歷起點位置,這樣可以保證在計算dp[i, j]時所需要的dp[i, k - 1]出現過(顯而易見,k - 1 在 j 左側),也保證dp[k + 1, j]出現過(也很顯然,因為長度小於當前長度),對於輸出前序遍歷,只需要在每次更新的時候記錄當前的根節點是哪乙個點即可,輸出的時候先輸出整個區間的根,然後依次往左往右遞迴即可

#include #include #include #include using namespace std;

typedef long long ll;

int n;

ll points[33], dp[33][33], root[33][33];

void out(int l, int r)

int main()

for (int len = 1; len <= n; len++)

else lef = dp[l][k - 1];

if(k == r)rig = 1;

else rig = dp[k + 1][r];

s = rig * lef + points[k];

if(l == r)s = points[k];

if(dp[l][r] < s)

}} }

printf("%d\n", dp[1][n]);

out(1, n);

return 0;

}

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...

NOIP2003 加分二叉樹題解

設乙個n 個節點的二叉樹t 的中序遍歷為 1,2,3,n 其中數字 1,2,3,n 為節點編號。每個節點都有乙個分數 均為正整數 記第j 個節點的分數為dj。二叉樹t 及它的每個子樹都有 乙個加分,任意一棵子樹s 包括t 本身 的加分等於s 的左子樹的加分 s 的右子樹的加分 s的根的分數。若某棵子...