P2937 激光电话

这题算是P1126 机器人搬重物的升级版。
P1126 机器人搬重物题解-传送门
大概上思路就是找最少转弯次数(为什么我想到了-横冲直撞QAQ)对于这类问题BFS最方便了。。

const z:array[1..4,1..2]of-1..1=((1,0),(0,1),(-1,0),(0,-1));//方便呀
var i,j,k:longint;
    m,n:longint;
    a:array[0..200,0..200,1..4{四个方向}]of boolean;//判断是否走过
    ch:char;
    fx,fy,lx,ly:longint;
    h,t:longint;
    x{记录横坐标},y{记录纵坐标},u{记录当前转了几个弯},pfx{记录方向}:array[0..400000]of longint;//队列
    sum:array[0..200,0..200]of longint;//测试时的数组QAQ
begin
  readln(n,m);
  for i:=1 to m do
  begin
    for j:=1 to n do
    begin
      read(ch);
      if ch='C' then//找到起点和终点
      if fx=0 then
      begin
        fx:=i;
        fy:=j;
      end
      else
      begin
        lx:=i;
        ly:=j;
      end;
      if ch<>'*' then 
      begin
      for k:=1 to 4 do
      a[i,j,k]:=true;
      end;
    end;
    readln;
  end;
  //////////////////////////////队列处理开始了
  h:=1;
  t:=1;
  x[1]:=fx;
  y[1]:=fy;
  u[1]:=0;
  pfx[1]:=0;
  //////////////////////////////队列处理结束了
  a[fx,fy,1]:=false;//起点不可以再走
  a[fx,fy,2]:=false;
  a[fx,fy,3]:=false;
  a[fx,fy,4]:=false;
  repeat//标准的bfs
    if (x[t]=lx) and (y[t]=ly) then//到了呀
    begin
      write(u[t]-1);//第一个点开始没有方向所以比题目多转了一次要-1
      exit;
    end;
    for i:=1 to 4 do
    if i<>pfx[t] then//不可以和之前方向相同
    if a[x[t]+z[i,1],y[t]+z[i,2],i] then
    begin
      inc(h);//先把第一个点入队列
      x[h]:=x[t]+z[i,1];
      y[h]:=y[t]+Z[i,2];
      u[h]:=u[t]+1;
      pfx[h]:=i;
      a[x[h],y[h],i]:=false;
      sum[x[h],y[h]]:=u[h];
      while a[x[h]+z[i,1],y[h]+z[i,2],i] do//直到撞到....不然一直走
      begin
        inc(h);//入队列
        x[h]:=x[h-1]+z[i,1];
        y[h]:=y[h-1]+Z[i,2];
        u[h]:=u[t]+1;
        pfx[h]:=i;
        a[x[h],y[h],i]:=false;
        sum[x[h],y[h]]:=u[h];
      end;
    end;
    inc(t);
  until t>h;//bfs结束了QAQ
end.

这题其实不难呀,感觉比P1126 机器人搬重物还简单…

猜你喜欢

转载自blog.csdn.net/sxy__orz/article/details/86561155