题目
题目描述
机器人移动学会(RMI)现在正尝试用机器人搬运物品。机器人的形状是一个直径1.61.6米的球。在试验阶段,机器人被用于在一个储藏室中搬运货物。储藏室是一个 N×M 的网格,有些格子为不可移动的障碍。机器人的中心总是在格点上,当然,机器人必须在最短的时间内把物品搬运到指定的地方。机器人接受的指令有:向前移动1步(Creep);向前移动2步(Walk);向前移动3 步(Run);向左转(Left);向右转(Right)。每个指令所需要的时间为1 秒。请你计算一下机器人完成任务所需的最少时间。
输入格式
第一行为两个正整数N,M(N,M≤50),下面N行是储藏室的构造,0表示无障碍,1表示有障碍,数字之间用一个空格隔开。接着一行有4个整数和1个大写字母,分别为起始点和目标点左上角网格的行与列,起始时的面对方向(东E,南S,西W,北N),数与数,数与字母之间均用一个空格隔开。终点的面向方向是任意的。
输出格式
一个整数,表示机器人完成任务所需的最少时间。如果无法到达,输出−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
输出
12
分析
这道题看似复杂,但是只要注意题目中的边界问题,剩下的就是常规的BFS流程了。
首先需要注意,机器人是一个圆,我们每次记录的是他的中心点,所以我们需要小心机器人的边界判定。其次,障碍物占据一个格子,这里规定障碍物是起始点在左上角的格子 。
我的思路是将每个坐标的到达时间都记录下来,也就是对每个坐标的到达时间进行记忆化,这里还要加入一个方向数组,是为了方便判定每个点的四周是否都被访问过。
首先判定直行可以走几步(0-3),将能走的坐标都加入到队列中,走完后再进行方向的变动。每次执行命令都要让时间加1,并将新坐标入队。
下面是AC代码,具体解题过程可以见我代码的注释~
代码
#include<iostream>
#include <queue>
using namespace std;
typedef struct{
int x,y,d; //分别对应列坐标、行坐标、朝向
} Site;
const int maxn = 55;
int n, m;
Site s, f; //起点,终点
int d; //当前方向
int dir[4][2] = {
{
1, 0}, {
0, 1}, {
-1, 0}, {
0, -1}}; //方向, 东南西北
int map[maxn][maxn];
int vis[maxn][maxn][4];