公司聚会(有一个重点地方)

题目描述

dd_engi所在的TIANYI公司要举办一次盛大的公司聚会。可惜的是,由于场地和花费的原因,不可能所有人都参加。现在的任务是拟定参加聚会人员的名单。
TIANYI公司的组织架构可以看做一棵有根多叉树。也就是说,在编号为1~N的所有N名员工中,除了最高管理者(编号为1)以外,每个员工都有且仅有一位直接上司;最高管理者则是这棵多叉树的“根”。这很好理解,对吗?另外,我们保证,员工的编号会大于他的直接上司的编号。
不同的员工对于聚会有着不同的要求,事实上,若邀请第i位员工(编号为i),在聚会中满足他的要求需要花费Ci元。另一方面,不同的员工在聚会中的“兴奋指数”也不同,第i位员工参加聚会的兴奋指数是Ei。
选择参加聚会的人员还有一个限制:为了使参加聚会的员工能够尽量放松,若邀请了某位员工,就不能邀请他的任何一位上司。这里“上司”的定义是这样的:最高管理者没有上司,其余所有员工的直接上司以及直接上司的所有上司都是他的上司。换句话说,某位员工的上司就是树中从他的节点走到根节点的路径上经过的所有节点(包括根结点,但不包括他自身)。
在满足上述限制的前提下,dd_engi希望参加聚会人员的兴奋指数之和最大,但同时他被告知,满足所有参加聚会人员的要求的总花费不得超过M元。那么,参加聚会人员的名单究竟应该怎样确定才最优呢?你需要求出的是最大的总兴奋指数。

数据范围
30%的数据满足N<=20。
100%的数据满足1 <= N <= 1024, 0 <= M <= 109, 0 <= Ci <= 1024, -1024 <= Ei <= 1024。

输入格式

第一行,两个空格隔开的整数,N与M。
第二行,N-1个整数,分别是第2位至第N位员工的直接上司的编号。
第三行,N个整数,分别是C1、C2……CN。
第四行,N个整数,分别是E1、E2……EN。

输出格式

只需输出一行一个整数,即最大的总兴奋指数。

样例输入

样例输出

 

 

很简单很简单的题

我很快地写完了 不管怎么改都只有20分 详情见下

type
  node=^point;
  point=record
          now:longint;
          next:node;
        end;
var
  a:array[0..1025] of node;
  c,e:array[0..1025] of longint;
  f:array[0..1025,0..110] of longint;
  n,m,ans:longint;

procedure init;
var aa,i:longint;
    p:node;
begin
  fillchar(f,sizeof(f),$f0);
  readln(n,m);
  for i:=1 to n do a[i]:=nil;
  for i:=2 to n do begin
    read(aa);
    new(p);p^.now:=i;p^.next:=a[aa];a[aa]:=p;
  end;
  for i:=1 to n do read(c[i]);
  for i:=1 to n do read(e[i]);
end;

function max(a1,a2:longint):longint;
begin
  if (a1>a2) then exit(a1) else exit(a2);
end;

procedure search(x:longint);
var p:node;
    i,j:longint;
begin
  if (f[x,0]>=0) then exit;
  f[x,0]:=0;
  p:=a[x];
  while (p<>nil) do begin
    search(p^.now);
    for i:=m downto 0 do
      for j:=0 to i do if (f[p^.now,j]>-252645136) and (f[x,i-j]>-252645136) then
        f[x,i]:=max(f[x,i],f[p^.now,j]+f[x,i-j]);
    p:=p^.next;
  end;
  if (c[x]<=m) then f[x,c[x]]:=max(f[x,c[x]],e[x]);
end;

procedure terminate;
var i:longint;
begin
  search(1);
  ans:=0;
  for i:=0 to m do ans:=max(ans,f[1,i]);
  writeln(ans);
end;

begin
  init;
  terminate;
end.

 

———————————————我是分割线———————————————

 for i:=m downto 0 do
      for j:=0 to i do if (f[p^.now,j]>-252645136) and (f[x,i-j]>-252645136) then
        f[x,i]:=max(f[x,i],f[p^.now,j]+f[x,i-j]);

 

开始我写的是for j:=i downto 0 do...

于是我就只有20分 经过一个伟大的人(持续膜拜)的观察 我终于知道我是哪里错了!

开始我最后算的j=0的情况 这时候得到f[x,i]:=max(f[x,i],f[p^.now,0]+f[x,i] ) 于是f[x,i]得到的东西可能重复!

 

结论:能不用滚动就不用滚动!能用01滚动就不用就地滚动!坑爹啊!

posted on 2011-11-08 22:06  ushiojamie  阅读(195)  评论(0编辑  收藏  举报