洛谷P1126 机器人搬重物

机器人移动学会(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());

}

有什么建议可以评论指出,本人小白(轻喷)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值