题目: | 加分二叉树 | |
来源: | Noip 2003T3 | |
题目大意: | 在中序遍历为(1,2,3,…,n)的各种二叉树中,选出加分最高的一棵二叉树,输出最 高加分和对此二叉树的前序遍历。 | |
数据范围: | n<30、分值<100、结果不会超过4,000,000,000 | |
样例: | 5 5 7 1 2 10 | 145 3 1 2 4 5 |
做题思路: | 树型dp,f[l,r]=max{f[l,i-1]*f[i+1,r]+a[i](l<=i<=r)},还要输出前序遍历。。 Root[l,r]表示l到r间的跟是root[l,r],然后递归输出 | |
知识点: | 树型dp,树的遍历 |
var
root:array[0..50,0..50]of longint;
f:array[0..50,0..50]of int64;
a:array[0..50]of longint;
n,i:longint;
function dp(l,r:longint):int64;
var
i:longint;
t,max:int64;
begin
iff[l,r]>=0 then exit(f[l,r]);{<记忆化>}
if l=rthen{<到叶子了>}
begin
f[l,r]:=a[l];
root[l,r]:=l;
exit(f[l,r]);
end;
ifl>r then{<超过叶子了→空子树>}
begin
f[l,r]:=1;
exit(f[l,r]);
end;
max:=0;
fori:=l to r do{<枚举根>}
begin
t:=dp(l,i-1)*dp(i+1,r)+a[i];
ift>max then
begin
max:=t;
root[l,r]:=i;
end;
end;
f[l,r]:=max;
exit(f[l,r]);
end;
procedure print(l,r:longint); {<先序遍历,貌似题是逐字节的,反正保万一输出时还搞了下格式>}
begin
ifl>r then exit;
if(l=1)and(r=n) then write(root[l,r])
else write(' ',root[l,r]);
print(l,root[l,r]-1);
print(root[l,r]+1,r);
end;
begin
assign(input,'binary.in');reset(input);
assign(output,'binary.out');rewrite(output);
readln(n);
fori:=1 to n do read(a[i]);
readln;
fillchar(f,sizeof(f),255);
writeln(dp(1,n));
print(1,n);
close(input);close(output);
end.
题目来源: http://yt.tyvj.cn:8080/Problem_Show.asp?id=1040