【原题】【noip 2003 T2】【动态规划】加分二叉树
問題
描述 Description
設一個n個節(jié)點的二叉樹tree的中序遍歷為(l,2,3,…,n),其中數(shù)字1,2,3,…,n為節(jié)點編號。每個節(jié)點都有一個分數(shù)(均為正整數(shù)),記第i個節(jié)點的分數(shù)為di,tree及它的每個子樹都有一個加分,任一棵子樹subtree(也包含tree本身)的加分計算方法如下:
subtree的左子樹的加分× subtree的右子樹的加分+subtree的根的分數(shù)
若某個子樹為空,規(guī)定其加分為1,葉子的加分就是葉節(jié)點本身的分數(shù)。不考慮它的空子樹。
試求一棵符合中序遍歷為(1,2,3,…,n)且加分最高的二叉樹tree。要求輸出;
(1)tree的最高加分
(2)tree的前序遍歷
輸入格式 Input Format
第1行:一個整數(shù)n(n<30),為節(jié)點個數(shù)。
第2行:n個用空格隔開的整數(shù),為每個節(jié)點的分數(shù)(分數(shù)<100)。
輸出格式 Output Format
第1行:一個整數(shù),為最高加分(結(jié)果不會超過4,000,000,000)。
第2行:n個用空格隔開的整數(shù),為該樹的前序遍歷。
?
分析
一看就是一道動態(tài)規(guī)劃,而且是樹形的。仔細分析題意我們發(fā)先中序遍歷的遍歷順序是——左根右。也就是說,一旦根的位置在一個中序遍歷之中確定,它的左邊的序列就是它的左子樹,右邊就是右子樹。那么整棵樹的最優(yōu)值就是左子樹的最優(yōu)值乘上右子樹的最優(yōu)值。
我們可以得到方程:f[i,j]表示中序遍歷中i~j這棵子樹能得到的最大加分 f[i,j]=max{f[i,k-1]*f[k+1,j]+f[k,k]}(i<=k<=j)方程一定要這么寫,因為我們要考慮子樹為空的情況,所以i到j中的任意一個點都可以作為這棵樹的根。循環(huán)時要先循環(huán)區(qū)間長度l,這就類似于區(qū)間類的動態(tài)規(guī)劃了,為什么呢。因為對于一個樹形的動態(tài)規(guī)劃,都是從下至上的。所以要先找到葉子節(jié)點,再逐層找到根節(jié)點。
邊界處理:將所有空子樹的值都賦為1。
反思
方程的正確性直接影響結(jié)果。有的時候方程不能改動,根題目的要求和數(shù)據(jù)結(jié)構(gòu)有關,要保證方程的正確性,保證每一步的最優(yōu)性。不同類型的動態(tài)規(guī)劃有相同的地方,其宗旨是無后效性和子結(jié)構(gòu)最優(yōu)性。
code
program liukee; varpath,f:array[0..50,0..50] of longint;i,n,j,k,l:longint;procedure outit(x,y:longint); beginif x>y then exit;write(path[x,y],' ');outit(x,path[x,y]-1);outit(path[x,y]+1,y); end;beginfilldword(f,sizeof(f)>>2,1);readln(n);for i:=1 to n dobeginread(f[i,i]);path[i,i]:=i;end;for l:=2 to n dofor i:=1 to n-1 dobeginj:=i+l-1;for k:=i to j doif f[i,k-1]*f[k+1,j]+f[k,k]>f[i,j] thenbeginf[i,j]:=f[i,k-1]*f[k+1,j]+f[k,k];path[i,j]:=k;end;end;writeln(f[1,n]);outit(1,n); end.轉(zhuǎn)載于:https://www.cnblogs.com/liukeke/archive/2010/11/16/1878515.html
總結(jié)
以上是生活随笔為你收集整理的【原题】【noip 2003 T2】【动态规划】加分二叉树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uml 中的小人
- 下一篇: 用Ant编译Flex项目的几点注意事项