题目大意
在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有N门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程a是课程b的先修课即只有学完了课程a,才能学习课程b)。一个学生要从这些课程里选择M门课程学习,问他能获得的最大学分是多少?
分析
一.因为是多叉树,所以要转换成二叉树。具体方法见:http://blog.csdn.net/a_loud_name/article/details/51344128
二.转完后就是一个简单的树形dp
F[x,y]=max{F[x.Lson,k-1]+F[x.Rson,y-k]+w[x]} 0<=k<=y
三.因为是转换后的二叉树,所以枚举转态时要注意改一改,具体见程序
代码
type
arr=record
l,r:longint;
end;
var
a:array[0..1000] of arr;
ls,b:array[0..1000] of longint;
f:array[-1..1000,-1..1000] of longint;
i,j,k:longint;
n,m:longint;
procedure dfs(r,l:longint);
var
i,j,k:longint;
begin
if r=-1 then exit;
if f[r,l]<>0 then exit;
if l=0
then
begin
f[r,l]:=0;
exit;
end;
if (a[r].l=-1) and (a[r].r=-1)
then begin
f[r,l]:=b[r];
exit;
end;
dfs(a[r].r,l);
if f[r,l]<f[a[r].r,l]
then f[r,l]:=f[a[r].r,l]; //修改部分
for i:=0 to l-1 do
begin
dfs(a[r].l,i);
dfs(a[r].r,l-i-1);
if f[r,l]<f[a[r].l,i]+f[a[r].r,l-i-1]+b[r]
then
f[r,l]:=f[a[r].l,i]+f[a[r].r,l-i-1]+b[r];
end;
end;
begin
readln(n,m);
fillchar(f,sizeof(f),0);
fillchar(a,sizeof(a),0);
fillchar(b,sizeof(b),0);
m:=m+1;
for i:=0 to n do
begin
ls[i]:=-1;
a[i].l:=-1;
a[i].r:=-1;
end;
for i:=1 to n do
begin
readln(j,b[i]);
if ls[j]=-1
then
begin
a[j].l:=i;
ls[j]:=i;
end
else
begin
a[ls[j]].r:=i;
ls[j]:=i;
end;
end;
dfs(0,m);
write(f[0,m]);
end.