rqnoj 愚蠢的矿工

题目描述

背景
Stupid 家族得知在HYC家的后花园里的中央花坛处,向北走3步,向西走3步,再向北走3步,向东走3步,再向北走6步,向东走3步,向南走12步,再向西走2步( - -||)就能找到宝藏的入口,而且宝藏都是藏在山里的,必须挖出来,于是Stupid家族派狗狗带领矿工队去挖宝藏.(HYC家的宝藏被狗狗挖走后有什么感想?)

描述
这个宝藏的制造者为了掩盖世人耳目,他做的宝藏是没有出口,只有入口,不少建造宝藏的人都死在里面.现在知道宝藏总共有N个分岔口,在分岔口处是有财宝的,每个宝藏点都有一个财富值.狗狗只带了M个人来,而且为了安全起见,在每个分岔口,必须至少留一个人下来,这个留下来的人可以挖宝藏(每个人只能挖一个地方的宝藏),这样才能保证不会迷路,而且这个迷宫有个特点,任意两点间有且只有一条路可通.狗狗为了让他的00开心,决定要尽可能地多挖些宝藏回去.现在狗狗的圈叉电脑不在身旁,只能求救于你了,你要知道,狗狗的终身幸福就在你手上了..(狗狗ps:00,你不能就这样抛弃偶……)

输入格式

第1行:两个正整数N,M .N表示宝藏点的个数,M表示狗狗带去的人数(那是一条懒狗,他自己可不做事)。(n<=1000,m<=100)
第2行:N个整数,第i个整数表示第i个宝藏的财富值.(保证|wi|<maxint)
第N+2行:两个非负整数A和B,表示A通向B,当A=0,表示A是入口.(保证A,B<=n)

输出格式

输出狗狗能带回去的宝藏的价值。

样例输入

4 3

5 6

2 4

1 2

0 1

2 3

3 4

样例输出

13

注:树形动态规划。对于多叉树,我们一般采用多叉树转化为二叉树来简化问题即左儿子右兄弟,这也是dfs过程中为什么必须进行f[x,k]=f[r[x],k]。

  
    
1 var
2 l,r,a:array[ 0 .. 1000 ] of longint;
3 f:array[ 0 .. 1000 , 0 .. 100 ] of longint;
4 i,j,k,m,n:longint;
5
6 function max(x,y:longint):longint;
7 begin
8 if x > y then exit(x);
9 exit(y);
10 end;
11
12 procedure dfs(x,k:longint);
13 var
14 i:longint;
15 begin
16 if x <= 0 then exit;
17 if k <= 0 then exit;
18 if f[x,k] > 0 then exit;
19 dfs(r[x],k);
20 f[x,k]: = f[r[x],k];
21 for i: = 0 to k - 1 do
22 begin
23 dfs(l[x],i);
24 dfs(r[x],k - i - 1 );
25 f[x,k]: = max(f[x,k],f[l[x],i] + f[r[x],k - i - 1 ] + a[x]);
26 end;
27 end;
28
29 begin
30 readln(n,m);
31 for i: = 1 to n do read(a[i]); readln;
32 for i: = 1 to n do
33 begin
34 readln(j,k);
35 r[k]: = l[j];
36 l[j]: = k;
37 end;
38 fillchar(f, sizeof (f), 0 );
39 dfs(l[ 0 ],m);
40 writeln(f[l[ 0 ],m]);
41 end.

你可能感兴趣的:(OJ)