解题报告 开发计划

1.        题目

2. 开发计划

   plan.pas/c/cpp

【问题描述】

DD战队的首领DDS最近几天很烦恼,DD战队想要继续开发新小陆,DDS必须马上制定出开发计划。新小陆可开发区域位于一片沼泽地中,数目不明,DD战队可以随便选择一个进行开发。DDS已经得到了前往沼泽地的地图,他可以清晰地看到自己所在的总部位于1号已开发区域,并且知道由1号已开发区域可以到达的每一片区域以及这些可以到达的区域可以到达的区域。这些区域包括已开发的和未开发(可开发)的,共有n个,每一个区域都有一个固定编号,从1~n;而且整个新小陆刚好有n-1条路径。由一个区域到达另一个区域需要一天,并且到达这个新的区域后不会再返回。

虽然不知道新小陆可开发区域的具体位置,但是DDS知道它们有共同的特征:一旦进入将无路可走,即没有新的区域可以到达。有的区域比较贫瘠,称之为P区域,在P区域会因为各种问题不得不逗留一天,然后才能继续前进;假如可开发区域也是P区域,那么逗留几天显然不是问题,P可开发区域和其他可开发区域等价。

知道这些并不能完全解决DDS的烦恼,由于DD战队的成员智商很低,到达一个区域后不知道权衡利弊,总是随便选择一个新的可以到达的区域前进,所以他们可能走了很久才到达一个可开发区域。

DD战队当然想尽量节省物资,所以战队只能提供足够m天使用的物资。DDS想知道他的队员们最不可能到达和最可能到达的可开发区域的编号,假如有多个地区情况类似,两个答案都输出编号最小的。

 

【输入格式】

第一行三个数,nmk。分别表示区域数目,物资可以承受的天数和P区域的数目;

第二行k个数(若k<>0),表示P区域的编号;

接下来n-1行,每行两个数表示相连的区域的编号。

【输出格式】

输出两行,第一行表示最不可能到达的可开发区域,第二行表示最可能到达的可开发区域。

 

【输入样例】

6 1 0

1 2

1 3

2 4

2 6

4 5

 

【输出样例】

5

3

 

【数据范围】

20%数据:2<=n<=20 , 2<=m<=50 , 0<=k<=5

100%数据:2<=n<=1000, 2<=m<=1000; 0<=k<=100

 

 

Hint

物资可以剩余。

2.        算法

这就是传说中的概率型动规。

首先,当花掉 0 天物资时,在节点一的概率为一(初始化)。

同一个节点转移到他的不同的子节点的概率是相等的,都是这个节点的概率在初一他的子节点数。

方程有两个参,一个是节点编号,一个是花掉了几天物资,它本身存的是花掉这几天物资,到达这一节点的概率。

然后,输出概率最大的和最小的。

然后,让输出的都是叶子节点的编号。

3.        注意事项

我讨厌概率!

4.        代码

概率动规 (LYF)

var

  f:array[0..1005,0..1005] of double;

  a:array[0..1000,0..1000] of boolean;

  b:array[0..1000,0..1000] of longint;

  pp,v:array[0..1000] of boolean;

  ans1,ans2,i,j,k,n,m,p,l:longint;

  now,p1,p2:double;

 

procedure dfs(x:longint);

var

  i:longint;

begin

  v[x]:=true;

  for i:=1 to n do

    if (a[x,i])and(not v[i]) then

      begin

        inc(b[x,0]);

        b[x,b[x,0]]:=i;

        dfs(i);

      end;

end;

 

begin

  assign(input,'plan.in'); reset(input);

  assign(output,'plan.out'); rewrite(output);

  readln(n,m,p);

  for i:=1 to p do

    begin

      read(k);

      pp[k]:=true;

    end;

  for i:=1 to n-1 do

    begin

      readln(j,k);

      a[j,k]:=true;

      a[k,j]:=true;

    end;

  dfs(1);

  f[1,0]:=1;

  for j:=0 to m-1 do

    for i:=1 to n do

      if f[i,j]>0 then

        begin

          k:=b[i,0];

          for l:=1 to k do

            if (pp[b[i,l]])and(b[b[i,l],0]<>0) then f[b[i,l],j+2]:=f[b[i,l],j+2]+f[i,j]/k else

              f[b[i,l],j+1]:=f[b[i,l],j+1]+f[i,j]/k;

        end;

  p2:=maxlongint; p1:=0;

  for j:=2 to n do

    begin

      now:=0;

      if b[j,0]<>0 then continue;

      for i:=1 to m do

        now:=now+f[j,i];

      if now>p1 then

        begin

          p1:=now;

          ans1:=j;

        end;

      if now<p2 then

        begin

          p2:=now;

          ans2:=j;

        end;

    end;

  writeln(ans2);

  writeln(ans1);

  close(input); close(output);

end.

原文地址:https://www.cnblogs.com/SueMiller/p/2213460.html