选课 树形动态规划

题目大意

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


posted @ 2016-05-08 11:01  一个响亮的蒟蒻  阅读(556)  评论(0编辑  收藏  举报