luogu1040 區間DP 加分二叉樹

2021-10-09 03:41:06 字數 1835 閱讀 9312

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 output
145

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