机器人移动学会(RMI)现在正尝试用机器人搬运物品。机器人的形状是一个直径 $1.6$ 米的球。在试验阶段,机器人被用于在一个储藏室中搬运货物。储藏室是一个 $N\times M$ 的网格,有些格子为不可移动的障碍。机器人的中心总是在格点上,当然,机器人必须在最短的时间内把物品搬运到指定的地方。机器人接受的指令有:
- 向前移动 $1$ 步(`Creep`);
- 向前移动 $2$ 步(`Walk`);
- 向前移动 $3$ 步(`Run`);
- 向左转(`Left`);
- 向右转(`Right`)。每个指令所需要的时间为 $1$ 秒。请你计算一下机器人完成任务所需的最少时间。
## 输入格式
第一行为两个正整数 $N,M\ (1\le N,M\le50)$,下面 $N$ 行是储藏室的构造,$0$ 表示无障碍,$1$ 表示有障碍,数字之间用一个空格隔开。接着一行有 $4$ 个整数和 $1$ 个大写字母,分别为起始点和目标点左上角网格的行与列,起始时的面对方向(东 $\tt E$,南 $\tt S$,西 $\tt W$,北 $\tt N$),数与数,数与字母之间均用一个空格隔开。终点的面向方向是任意的。
## 输出格式
一个整数,表示机器人完成任务所需的最少时间。如果无法到达,输出 $-1$。
![](https://cdn.luogu.com.cn/upload/image_hosting/mma661em.png)## 样例 #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
```### 样例输出 #
12
写一篇题解,思路我感觉还算简单,但是花了差不多4个多小时才debug玩,只能说坑还是有点多的。
思路:
一般的bfs。。。
只是多了几步处理。首先机器人在格点上运动,这是第一个坑,要把格的输入转换成点数组。其次,就是把四个方向的点看成不同的点,不然st数组标记有问题。接着就是用2维数组存不同方向上的运动步数。最后要注意机器人不能在边缘点上运动!!!(这个坑卡了我两个数据点一个多小时)还有不要忘了特判,比如初始点为障碍点,起点与终点相同。
代码附上:
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
const int N = 60,M=N*N*4;
struct PII {
int sx, sy;
char sc;
};//存点信息
int g[N][N][4];
int g1[N][N][4];
int g2[N][N];
bool st[N][N][4];
int n, m;
PII p[M];
PII past[N][N][4];//记录路线
int cnt[N] ;//记数数组其实可以用cnt代替(画蛇添足)
int dx[4][3] = { {-1,-2,-3},{0,0,0},{1,2,3},{0,0,0} };
int dy[4][3] = { {0,0,0},{1,2,3},{0,0,0},{-1,-2,-3} };//移动数组
int a, b, c, d;//起始点,终点
char s;
int idx;
//E +y, W -y,S +x,N -x;
int bfs() {
if (g1[a][b][1] == 1) {
return -1;
}
else if (a == c && b == d) {
return 0;
}
else {
int tt = -1, hh = 0;
p[++tt] = { a,b ,s };
if (s == 'N') {
st[a][b][0] = true;
}
else if (s == 'E') {
st[a][b][1] = true;
}
else if (s == 'S') {
st[a][b][2] = true;
}
else {
st[a][b][3] = true;
}
while (tt >= hh) {
PII t = p[hh++];
int xx = t.sx;;
int yy = t.sy;
char C = t.sc;
for (int i = 0;i < 3;i++) {
int j;
if (C == 'N') {
j = 0;
}
else if (C == 'E') {
j = 1;
}
else if (C == 'S') {
j = 2;
}
else {
j = 3;
}
int x = xx + dx[j][i];
int y = yy + dy[j][i];
if (g1[x][y][j] == 1) {
break;
}
if (x > 0 && x < n && y > 0 && y < m && !st[x][y][j]) {
p[++tt] = { x,y,C };
past[x][y][j] = { xx,yy,C };
st[x][y][j] = true;
if (x == c && y == d) {
char rc;
int l, h, f;
int l0, h0, f0;
for (l = x, f = y, h = j, rc = C;l != a || f != b || rc != s;l = past[l0][f0][h0].sx, f = past[l0][f0][h0].sy, rc = past[l0][f0][h0].sc) {
if (rc == 'N') {
h = 0;
}
else if (rc == 'E') {
h = 1;
}
else if (rc == 'S') {
h = 2;
}
else {
h = 3;
}
cnt[idx]++;
l0 = l, h0 = h, f0 = f;
}idx++;
}
}
}
for (int i = 1;i <= 2;i++) {
int j;int k = 0;char cc;
if (C == 'N') {
j = 0;
}
else if (C == 'E') {
j = 1;
}
else if (C == 'S') {
j = 2;
}
else {
j = 3;
}
if (i == 1) {
k = (j + 1) % 4;
}
else {
k = (j + 3) % 4;
}
if (k == 0) {
cc = 'N';
}
else if (k == 1) {
cc = 'E';
}
else if (k == 2) {
cc = 'S';
}
else {
cc = 'W';
}
if (!st[xx][yy][k]) {
p[++tt] = { xx,yy,cc };
past[xx][yy][k] = { xx,yy,C };
st[xx][yy][k] = true;
}
}
}
if (cnt[0] == 0) {
return -1;
}
else {
int o = 0x3f3f;
for (int i = 0;i < idx;i++) {
o = min(o, cnt[i]); //可以不要这一步
}return o;
}
}
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= m;j++) {
scanf("%d", &g2[i][j]);
}
}
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= m;j++) {
for (int k = 0;k < 4;k++) {
g[i][j][k] = g2[i][j];
}
}
}
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= m;j++) {
for (int k = 0;k < 4;k++) {
if (g[i][j][k] == 1) {
g1[i - 1][j - 1][k] = 1;
g1[i - 1][j][k] = 1;
g1[i][j - 1][k] = 1;
g1[i][j][k] = 1;
}
}
}
}
/*for (int i = 0;i <= n;i++) {
for (int j = 0;j <= m;j++) {
printf("%d ", g1[i][j][0]);
}
printf("\n");
}*/
scanf("%d%d%d%d", &a, &b, &c, &d);
cin >> s;
printf("%d", bfs());
}
有什么建议可以评论指出,本人小白(轻喷)。