聪聪和可可

聪聪与可可
在一个魔法森林里,住着一只聪明的小猫聪聪和一只可爱的小老鼠可可。 整个森林可以认为是一个无向图,图中有N个美丽的景点,景点从1至N编号。在景点之间有一些路连接。 可可正在景点M (M ≤ N)处。以后的每个时间单位,可可都会选择去相邻的景点(可能有多个)中的一个或停留在原景点不动。而去这些地方所发生的概率是相等的。 聪聪是很聪明的,所以,当她在景点C时,她会选一个更靠近可可的景点,如果这样的景点有多个,她会选一个标号最小的景点。如果走完第一步以后仍然没吃到可可,她还可以在本段时间内再向可可走近一步。 在每个时间单位,假设聪聪先走,可可后走。在某一时刻,若聪聪和可可位于同一个景点,则可可就被吃掉了。 问平均情况下,聪聪几步就可能吃到可可。


n、e<=1000


noi2005,原题懒得贴了


首先预处理每个点往每个点应当走的下一个点,即为p[i,j]

然后动规

用f[i,j]表示猫在i老鼠在j的平均步数

记忆化搜索一下就好了


program cchkk;
var
  tot,n,e,i,j,k,u,v,c,m:longint;
  dl,t,root:array [0..1001] of longint;
  p,dis:array [0..1001,0..1001] of longint;
  f:array [0..1001,0..1001] of double;
  yes:array [0..1001,0..1001] of boolean;
  point,next:array [0..2001] of longint;

procedure connect (u,v:longint);
begin
  inc(tot);
  point[tot]:=v;
  next[tot]:=root[u];
  root[u]:=tot;
  inc(t[u]);
end;

procedure spfa (sta:longint);
var
  i,j,k:longint;
begin
  tot:=1;
  dl[1]:=sta;
  i:=1;
  dis[sta,sta]:=0;
  while i<=tot do
    begin
      k:=root[dl[i]];
      while k<>0 do
        begin
          if dis[sta,point[k]]>dis[sta,dl[i]]+1 then
            begin
              dis[sta,point[k]]:=dis[sta,dl[i]]+1;
              inc(tot);
              dl[tot]:=point[k];
            end;
          if (dis[sta,point[k]]=dis[sta,dl[i]]+1)and
          (p[point[k],sta]>dl[i]) then p[point[k],sta]:=dl[i];
          k:=next[k];
        end;
      inc(i);
    end;
end;

function search (x,y:longint):double;
var
  i,k:longint;
  ans:double;
begin
  if yes[x,y] then exit(f[x,y]);
  if p[x,y]=y then
    begin
      yes[x,y]:=true;
      f[x,y]:=1;
      exit(1);
    end;
  ans:=0;
  if p[p[x,y],y]=y then
    ans:=ans+t[y]/(t[y]+1)
                   else
    begin
      k:=root[y];
      while k<>0 do
        begin
          ans:=ans+(search(p[p[x,y],y],point[k])+1)/(t[y]+1);
          k:=next[k];
        end;
    end;
  ans:=ans+(search(p[p[x,y],y],y)+1)/(t[y]+1);
  f[x,y]:=ans;
  yes[x,y]:=true;
  exit(ans);
end;

begin
  assign(input,'cchkk.in');
  reset(input);
  assign(output,'cchkk.out');
  rewrite(output);
  read(n,e);
  read(c,m);
  for i:=1 to e do
    begin
      read(u,v);
      connect(u,v);
      connect(v,u);
    end;
  fillchar(dis,sizeof(dis),63);
  fillchar(p,sizeof(p),63);
  for i:=1 to n do
    spfa(i);
  fillchar(yes,sizeof(yes),false);
  for i:=1 to n do
    begin
      f[i,i]:=0;
      yes[i,i]:=true;
    end;
  writeln(search(c,m):0:3);
  close(input);
  close(output);
end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值