1. 程式人生 > 其它 >【ybtoj】【BFS】【例題3】立體推箱子

【ybtoj】【BFS】【例題3】立體推箱子

技術標籤:ybtoj搜尋

【例題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); } }