洛谷 P1126 机器人搬重物

题目描述

机器人移动学会(RMI)现在正尝试用机器人搬运物品。机器人的形状是一个直径1.6米的球。在试验阶段,机器人被用于在一个储藏室中搬运货物。储藏室是一个N*M的网格,有些格子为不可移动的障碍。机器人的中心总是在格点上,当然,机器人必须在最短的时间内把物品搬运到指定的地方。机器人接受的指令有:向前移动1步(Creep);向前移动2步(Walk);向前移动3步(Run);向左转(Left);向右转(Right)。每个指令所需要的时间为1秒。请你计算一下机器人完成任务所需的最少时间。

这里写图片描述
输入输出格式

输入格式:
输入的第一行为两个正整数N,M(N,M<=50),下面N行是储藏室的构造,0表示无障碍,1表示有障碍,数字之间用一个空格隔开。接着一行有四个整数和一个大写字母,分别为起始点和目标点左上角网格的行与列,起始时的面对方向(东E,南S,西W,北N),数与数,数与字母之间均用一个空格隔开。终点的面向方向是任意的。

输出格式:
一个整数,表示机器人完成任务所需的最少时间。如果无法到达,输出-1。

输入输出样例

输入样例#1:
9 10
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 1 0
7 2 2 7 S
输出样例#1:
12

分析:先把图上的格坐标变为点坐标(一个格变4个点,因为机器人其实就是占了一个点)。然后再暴力搜索。因为如果每次达到的点已经来过,就不管了,减少时间(能跑绝对不走,能走绝对不爬,机器人好可怜)

代码:

const
 maxn=300000;
var
  fang:array[1..4,1..3,1..2] of longint;
  h:array[0..maxn,1..4] of longint;
  a:array[0..51,0..51] of longint;
  f:array[0..51,0..51,1..4] of boolean;
  b:array[0..51,0..51] of boolean;
  head,tail,i,j,k,s,n,m,x,y,z,xx,yy,zz,x1,x2,y1,y2:longint;
  ch:char;

function pre(sx:longint):longint;
begin
  if sx=1 then exit(4) else exit(sx-1);
end;

function next(sx:longint):longint;
begin
  if sx=4 then exit(1) else exit(sx+1);
end;

begin
  for i:=1 to 3 do
    begin
      fang[1,i,1]:=-i;
      fang[2,i,2]:=-i;
      fang[3,i,1]:=i;
      fang[4,i,2]:=i;
    end;
  readln(m,n);
  for i:=1 to m do
    for j:=1 to n do
      read(a[i,j]);
  dec(m); dec(n);
  for i:=1 to m do
    for j:=1 to n do
      if (a[i,j]=0) and (a[i+1,j]=0) and (a[i,j+1]=0) and (a[i+1,j+1]=0) then
        begin
          for k:=1 to 4 do
            f[i,j,k]:=true;
          b[i,j]:=true;
        end;
  read(x1,y1,x2,y2);
  if (x1=x2) and (y1=y2) then begin writeln(0); halt; end;{这算打点吗}
  if not b[x1,y1] or not b[x2,y2] then begin writeln(-1);halt; end;
  read(ch);
  read(ch);
  case ch of
    'N':s:=1;
    'W':s:=2;
    'S':s:=3;
    'E':s:=4;
  end;
  f[x1,y1,s]:=false;
  h[1,1]:=x1;
  h[1,2]:=y1;
  h[1,3]:=s;
  head:=0;
  tail:=1;
  while head<tail do
    begin
      head:=head mod maxn+1;
      x:=h[head,1];
      y:=h[head,2];
      z:=h[head,3];
      zz:=pre(z);
      if f[x,y,zz] then
        begin
          tail:=tail mod maxn+1;
          h[tail,1]:=x;
          h[tail,2]:=y;
          h[tail,3]:=zz;
          h[tail,4]:=h[head,4]+1;
          f[x,y,zz]:=false;
        end;
      zz:=next(z);
      if f[x,y,zz] then
        begin
          tail:=tail mod maxn+1;
          h[tail,1]:=x;
          h[tail,2]:=y;
          h[tail,3]:=zz;
          h[tail,4]:=h[head,4]+1;
          f[x,y,zz]:=false;
        end;
      for i:=1 to 3 do
        begin
          xx:=x+fang[z,i,1];
          yy:=y+fang[z,i,2];
          if f[xx,yy,z] then
            begin
              tail:=tail mod maxn+1;
              h[tail,1]:=xx;
              h[tail,2]:=yy;
              h[tail,3]:=z;
              h[tail,4]:=h[head,4]+1;
              f[xx,yy,z]:=false;
              if (xx=x2) and (yy=y2) then
                begin
                  writeln(h[tail,4]);
                  halt;
                end;
            end else if not b[xx,yy] then break;
        end;
    end;
  writeln(-1);
end.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值