description
設乙個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的前序遍歷
input
第1行:乙個整數n(n<30),為節點個數。
第2行:n個用空格隔開的整數,為每個節點的分數(分數<100)。
output
第1行:乙個整數,為最高加分(結果不會超過4,000,000,000)。
第2行:n個用空格隔開的整數,為該樹的前序遍歷。
sample input
5
5 7 1 2 10
sample output145
3 1 2 4 5
解題思路
題目大意
給你乙個中序遍歷的tree,輸入樹上每個節點的基礎分
以當前節點為根的樹,也就是子樹(subtree)
每個節點的分數=subtree的左子樹的分數× subtree的右子樹的分數+當前節點的基礎分
(寫這個是因為我看不懂題目tot) 設f[i
][j]
f[i][j]
f[i][j
]為從i
ii到j
jj的節點組成一棵子樹的分數,roo
t[i]
[j
]root[i][j]
root[i
][j]
為從i
ii到j
jj的節點組成一棵子樹的根
code
#include
#include
using namespace std;
int n,check,a[50]
,root[50]
[50];
long long sum,f[50]
[50];
void
output
(int l,int r)
printf
("%d "
,root[l]
[r])
;//根
output
(l,root[l]
[r]-1)
;//左
output
(root[l]
[r]+
1,r)
;//右
}int main()
for(int len=
2;len<=n;len++
)//區間長度(i~j的長度)
for(int i=
1;i<=n-len+
1;i++)if
(j>mid)
if(check)sum*=f[mid+1]
[j];
else sum=f[mid+1]
[j];
sum+=a[mid];if
(sum>f[i]
[j])}}
printf
("%lld\n"
,f[1
][n]);
output(1
,n);
}
luogu1040 加分二叉樹
題目傳送門 這道題一看題目就大概知道是一道樹狀dp,我們就要想轉移方程式是個什麼樣子了。首先我們很好能想出來要從下往上不斷轉移狀態,所以我們要先預處理出來dp i i a i dp i i a i dp i i a i 然後不斷轉移。然後轉移方程該怎麼想呢?方程很明顯就是看看怎麼分答案最大就好了,但...
合併遊戲 737 區間Dp
石子合併 一 時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述 有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。輸入 有多組測試資...
P1040 加分二叉樹 區間dp
設乙個nn個節點的二叉樹tree的中序遍歷為 1,2,3,n1,2,3,n 其中數字1,2,3,n1,2,3,n為節點編號。每個節點都有乙個分數 均為正整數 記第ii個節點的分數為di,treedi,tree及它的每個子樹都有乙個加分,任一棵子樹subtreesubtree 也包含treetree本...