将功补过 树形动态规划

题目大意

   对于一个二叉树,除根节点外,每个节点都有相应的一个权值。在此基础上,求保留多少个点使得其仍然满足树的性质且权值总和最大。


分析

  具体方法见:http://blog.csdn.net/a_loud_name/article/details/51326123


代码


var
  f:array[0..200,0..200] of longint;
  a:array[0..200,1..3] of longint;
  b:array[0..200,0..200] of longint;
  v,num:array[0..200] of longint;
  i,j,k,l:longint;
  n,m,nm:longint;
  ans:longint;

procedure make(v:longint);
var
  i,j,k:longint;
begin
  for i:=1 to n do
    begin
      if b[v,i]>0 then
        begin
          a[v,1]:=i;
          num[i]:=b[v,i]-1;
          b[v,i]:=-1; b[i,v]:=-1;
          make(i);
          break;
        end;
    end;
  for i:=1 to n do
    begin
      if b[v,i]>0 then
        begin
          a[v,2]:=i;
          num[i]:=b[v,i]-1;
          b[v,i]:=-1; b[i,v]:=-1;
          make(i);
          break;
        end;
    end;
end;

procedure dfs(r,l:longint);
var
  i,j,k:longint;
begin
  if f[r,l]<>0 then exit;
  if l=0
    then
      begin
        f[r,l]:=0;
        exit;
      end;
  if (a[r,1]=0) and (a[r,2]=0)
    then begin
      f[r,l]:=num[r];
      exit;
    end;
  for i:=0 to l-1 do
    begin
      dfs(a[r,1],i);
      dfs(a[r,2],l-i-1);
      if f[r,l]<f[a[r,1],i]+f[a[r,2],l-i-1]+num[r]
        then
          f[r,l]:=f[a[r,1],i]+f[a[r,2],l-i-1]+num[r];
    end;
end;

begin
  readln(n,m,nm);
  m:=m+1;
  for i:=1 to n-1 do
    begin
      readln(j,k,l);
      b[j,k]:=l+1;
      b[k,j]:=l+1;
    end;
  fillchar(f,sizeof(f),0);
  fillchar(v,sizeof(v),0);
  fillchar(a,sizeof(a),0);
  v[0]:=1;
  make(1);
  dfs(1,m);
  if nm<=f[1,m] then writeln('TRUE')
                else writeln('FALSE');
  writeln(f[1,m]-nm);
end.





posted @ 2016-05-10 16:41  一个响亮的蒟蒻  阅读(114)  评论(0编辑  收藏  举报