选课 树形动态规划
题目大意
在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有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.