題目大意:
構造一顆 n
nn 個節點的二叉樹,其編號為 1,2
,3,…
,n
1,2,3,…,n
1,2,3,
…,n ,每個節點都有乙個權值 w
iw_i
wi子樹的權值 =
== 左子樹權值 ∗
*∗ 右子樹權值 +
++ 根節點權值
若某個子樹為空,規定其權值為 1
11。葉子的加分就是葉節點本身的分數,不考慮它的空子樹。
試求一棵符合中序遍歷的節點編號為 1,2
,3,…
,n
1,2,3,…,n
1,2,3,
…,n且加分最高的二叉樹
輸出其整棵樹的最高分和此分數下字典序最小的前序遍歷
題目分析:
因為此二叉樹的中序遍歷為 1,2
,3,.
..,n
1,2,3,...,n
1,2,3,
...,
n ,當我們確定根節點編號為 k
kk 時,其左子樹的節點編號一定為 1
11 到 k−1
k-1k−
1 ,右子樹的節點編號一定為 k
kk 到 n
nn ,是互不影響的,我們考慮區間 dpdp
dp設 d p[
i][j
]dp[i][j]
dp[i][
j]表示編號為 i
ii 到 j
jj 這一段構成的子樹的最大權值
容易有轉移方程:
d p[
i][j
]=ma
x(dp
[i][
k−1]
∗dp[
k+1]
[j]+
w[k]
)dp[i][j]=max(dp[i][k-1]*dp[k+1][j]+w[k])
dp[i][
j]=m
ax(d
p[i]
[k−1
]∗dp
[k+1
][j]
+w[k
])而此題還要求方案,且字典序最小,那麼一定要有先轉移 k
kk 較小的情況,所以我們只需要邊轉移邊記錄,最後遞迴輸出方案即可
具體細節見**:
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define inf 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f3f
//#define int ll
using
namespace std;
intread()
while
(ch>=
'0'&& ch<=
'9')
return res*flag;
}const
int maxn =
105;
const
int mod =
1e9+7;
const
double pi =
acos(-
1);const
double eps =
1e-8
;struct nodenod[maxn*maxn]
;int n,w[maxn]
,dp[maxn]
[maxn]
,root[maxn]
[maxn]
;//root[i][j]表示dp[i][j]從**轉移過來的
void
dfs(
int l,
int r)
signed
main()
}}printf
("%d\n"
,dp[1]
[n])
;dfs(1
,n);
return0;
}
Acwing 479 加分二叉樹(區間dp)
495 老師用了區間dp dp l r 是左邊界l,右邊界r的最大加分 同時還需要設乙個k表示根節點,然後dp l k 1 表示左子樹最大加分,dp k 1 r 表示有指數最大加分。然後遍歷這 一區間最大的加分就可,題目中要求輸出乙個前序的序列,那我們把每乙個最大區間也就是dp l k 1 dp k...
479 加分二叉樹
原題傳送門 設乙個n個節點的二叉樹tree的中序遍歷為 1,2,3,n 其中數字1,2,3,n為節點編號。每個節點都有乙個分數 均為正整數 記第i個節點的分數為di,tree及它的每個子樹都有乙個加分,任一棵子樹subtree 也包含tree本身 的加分計算方法如下 subtree的左子樹的加分 s...
加分二叉樹
描述 設乙個n個節點的二叉樹tree的中序遍歷為 l,2,3,n 其中數字1,2,3,n為節點編號。每個節點都有乙個分數 均為正整數 記第i個節點的分數為di,tree及它的每個子樹都有乙個加分,任一棵子樹subtree 也包含tree本身 的加分計算方法如下 subtree的左子樹的加分 subt...