洛谷P1126《机器人搬重物》
原更新日期:2019-01-10 22:06:16
机器人有直径
题目描述
机器人移动学会(RMI)现在正尝试用机器人搬运物品。机器人的形状是一个直径\(1.6\)米的球。在试验阶段,机器人被用于在一个储藏室中搬运货物。储藏室是一个\(N \times M\)的网格,有些格子为不可移动的障碍。机器人的中心总是在格点上,当然,机器人必须在最短的时间内把物品搬运到指定的地方。机器人接受的指令有:向前移动\(1\)步(Creep);向前移动\(2\)步(Walk);向前移动\(3\)步(Run);向左转(Left);向右转(Right)。每个指令所需要的时间为\(1\)秒。请你计算一下机器人完成任务所需的最少时间。
输入输出格式
输入格式
第一行为两个正整数\(N,M(N,M \le 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
解题思路
1. 将格子图转为点图 & 障碍物判断
要注意这个机器人是有直径的,所以边界和障碍物的四周都不能走
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
int ttt;
scanf("%d", &ttt);
if (ttt) {
map[i][j] = map[i][j - 1] = map[i - 1][j] = map[i - 1][j - 1] = 1;
}
}
}
2.单向 BFS
枚举所有的步数和方向
3.三维数组判重
要注意本题是有方向的,所以vis数组需要开三维(vis[N][M][方向]
)
代码实现
/* -- Basic Headers -- */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
/* -- STL Iterators -- */
#include <vector>
#include <string>
#include <stack>
#include <queue>
/* -- External Headers -- */
#include <map>
#include <cmath>
/* -- Defined Functions -- */
#define For(a,x,y) for (int a = x; a <= y; ++a)
#define Forw(a,x,y) for (int a = x; a < y; ++a)
#define Bak(a,y,x) for (int a = y; a >= x; --a)
namespace FastIO {
inline int getint() {
int s = 0, x = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') x = -1;
ch = getchar();
}
while (isdigit(ch)) {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * x;
}
inline void __basic_putint(int x) {
if (x < 0) {
x = -x;
putchar('-');
}
if (x >= 10) __basic_putint(x / 10);
putchar(x % 10 + '0');
}
inline void putint(int x, char external) {
__basic_putint(x);
putchar(external);
}
}
namespace Solution {
const int dx[] = { 0, 1, 0, -1 };
const int dy[] = { 1, 0, -1, 0 };
const int MAXN_M = 50 + 10;
struct Robot {
int x, y;
int dir;
int step;
};
std::queue<Robot> q;
bool vis[MAXN_M][MAXN_M][4];
bool map[MAXN_M][MAXN_M];
int n, m;
int startx, starty, endx, endy, sd;
char startdir;
}
signed main() {
#define HANDWER_FILE
#ifndef HANDWER_FILE
freopen("testdata.in", "r", stdin);
freopen("testdata.out", "w", stdout);
#endif
using namespace Solution;
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
int ttt;
scanf("%d", &ttt);
if (ttt) {
map[i][j] = map[i][j - 1] = map[i - 1][j] = map[i - 1][j - 1] = 1;
}
}
}
scanf("%d %d %d %d %c", &startx, &starty, &endx, &endy, &startdir);
switch(startdir) {
case 'E': {
sd = 0;
break;
}
case 'S': {
sd = 1;
break;
}
case 'W': {
sd = 2;
break;
}
default: {
sd = 3;
break;
}
} // 对方向进行处理
if (startx >= n || startx < 1 || starty >= m || starty < 1 || map[startx][starty]) {
puts("-1");
return 0;
}
Robot rb;
rb.x = startx;
rb.y = starty;
rb.dir = sd;
rb.step = 0;
vis[startx][starty][sd] = true;
q.push(rb);
// 开始 BFS
while (!q.empty()) {
rb = q.front();
q.pop();
int newx = rb.x;
int newy = rb.y;
if (newx == endx && newy == endy) {
printf("%d\n", rb.step);
return 0;
}
// 枚举步数
for (int steps = 1; steps <= 3; ++steps) {
newx += dx[rb.dir];
newy += dy[rb.dir];
if (newx < 1 || newx >= n || newy < 1 || newy >= m || map[newx][newy]) {
break;
}
if (!vis[newx][newy][rb.dir]) {
vis[newx][newy][rb.dir] = true;
Robot nown;
nown.x = newx;
nown.y = newy;
nown.dir = rb.dir;
nown.step = rb.step + 1;
q.push(nown);
}
}
// 更新步数
Robot nown = rb;
++nown.step;
--nown.dir;
if (nown.dir == -1) nown.dir = 3;
if (!vis[nown.x][nown.y][nown.dir]) {
vis[nown.x][nown.y][nown.dir] = true;
q.push(nown);
}
nown.dir = rb.dir + 1;
if (nown.dir == 4) nown.dir = 0;
if (!vis[nown.x][nown.y][nown.dir]) {
vis[nown.x][nown.y][nown.dir] = true;
q.push(nown);
}
}
puts("-1");
return 0;
}