【ybtoj】【BFS】【例題3】立體推箱子
阿新 • • 發佈:2021-01-13
【例題3】立體推箱子
Link
解題思路
記錄狀態時將座標和木塊狀態一起記錄
(
q
[
x
]
[
y
]
[
t
]
)
(q[x][y][t])
(q[x][y][t])
對於2狀態,座標預設是下面那一塊
對於3狀態,座標預設是右邊那一塊
有幾個需要注意的旋轉時座標的改變
Code
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int xw[ 4][5] = {{}, {-1, 0, 2}, {-2, 0, 1}, {-1, 0, 1}};//把座標的改變預處理出來
const int yw[4][5] = {{}, {0, 2, 0, -1}, {0, 1, 0, -1}, {0, 1, 0, -2}};
const int tw[4][5] = {{}, {2, 3, 2, 3}, {1, 2, 1, 2}, {3, 1, 3, 1}};
int n, m, s[510][510][5], q[750100][3], h, t, v[510][510][5];
int sx, sy, st, ex, ey, et, ans;
char a[510][510];
void initial() {
st = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (a[i][j] == 'X' && !st) {
if (a[i + 1][j] == 'X')//狀態2
sx = i + 1, sy = j, st = 2;
else
if (a[i][j + 1] == 'X')//狀態3
sx = i, sy = j + 1, st = 3;
else
sx = i, sy = j, st = 1;//只有一個‘X’是狀態1
}
if (a[i][j] == 'O')
ex = i, ey = j, et = 1;
}
}
bool check(int x, int y, int t) {
if (x < 0 || x > n || y < 0 || y > m)
return 0;
if (t == 1) {
if (a[x][y] == 'E' || a[x][y] == '#')//不可以立在易碎地面上
return 0;
}
if (t == 2) {
if (a[x][y] == '#' || a[x - 1][y] == '#')
return 0;
}
if (t == 3) {
if (a[x][y] == '#' || a[x][y - 1] == '#')
return 0;
}
return 1;
}
bool BFS() {
h = t = s[sx][sy][st] = 0;
q[++t][0] = sx, q[t][1] = sy, q[t][2] = st;
while (h++ < t) {
for (int i = 0; i < 4; i++) {
int xx = q[h][0] + xw[q[h][2]][i];
int yy = q[h][1] + yw[q[h][2]][i];
int tt = tw[q[h][2]][i];
if (check(xx, yy, tt) && //判斷當前的(xx, yy, tt)可不可行
!v[xx][yy][tt]) {//判斷(xx, yy, tt)走沒走過
s[xx][yy][tt] = s[q[h][0]][q[h][1]][q[h][2]] + 1;//記錄步數
v[xx][yy][tt] = 1, q[++t][0] = xx, q[t][1] = yy, q[t][2] = tt;
if (xx == ex && yy == ey && tt == et) {//走到‘O’上
printf("%d\n", s[ex][ey][et]);
return 0;
}
}
}
}
return 1;
}
int main() {
scanf("%d%d", &n, &m);
while (n && m) {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin>>a[i][j];
initial();//預處理
if (BFS())
printf ("Impossible\n");
//*****************************************
ans = 0;
memset(v, 0, sizeof(v));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] = '\0';
//清空*************************************
scanf("%d%d", &n, &m);
}
}