洛谷P1126《机器人搬重物》

有直径还写个锤

题目描述

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

输入输出样例

输入样例

1
2
3
4
5
6
7
8
9
10
11
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

解题思路

1. 将格子图转为点图 & 障碍物判断

要注意这个机器人是有直径的,所以边界和障碍物的四周都不能走

1
2
3
4
5
6
7
8
9
10
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][方向]

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/* -- 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;
}