洛谷P1126《機器人搬重物》
阿新 • • 發佈:2020-10-14
原更新日期: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;
}