解题思路
首先这个是广搜。
可以预处理出刚开始的箱子状态和终点。
那么 1 × 2 1×2 1×2 的情况怎么记录呢?
我们可以记录第一个格子,然后直接把第二个格子判断状态即可。
然后对于箱子的移动很麻烦,我们要用 d x , d y dx,dy dx,dy表示移动方向, d t dt dt表示移动后的状态。
最后直接搜就好了。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <cmath>
using namespace std;
const int dx[4][5] = {
{
}, {
0, 0, 0, -2, 1 }, {
0, 1, -1, 0, 0 }, {
0, 0, 0, 2, -1 } };
const int dy[4][5] = {
{
}, {
0, 1, -2, 0, 0 }, {
0, 0, 0, 2, -1 }, {
0, 1, -1, 0, 0 } };
const int dt[4][5] = {
{
}, {
0, 2, 2, 3, 3 }, {
0, 2, 2, 1, 1 }, {
0, 3, 3, 1, 1 } };
char lyx[600][600];
bool flag = 0;
int n, m, h, t, tx, ty, v[600][600][4];
struct c {
int x, y, t, c;
} a[6000000];
bool check(int x, int y, int t) {
if (x < 1 || y < 1 || x > n || y > m || v[x][y][t] == 1)
return 0;
if (t == 1) {
if (lyx[x][y] == '#' || lyx[x][y] == 'E')
return 0;
}
if (t == 2) {
if (lyx[x][y] == '#' || lyx[x][y + 1] == '#' || y + 1 > m)
return 0;
}
if (t == 3) {
if (lyx[x][y] == '#' || lyx[x + 1][y] == '#' || x + 1 > n)
return 0;
}
return 1;
}
void bfs() {
h = 0, t = 1;
while (h < t) {
h++;
for (int i = 1; i <= 4; i++) {
int xx = a[h].x + dx[a[h].t][i], yy = a[h].y + dy[a[h].t][i], tt = dt[a[h].t][i];
if (check(xx, yy, tt)) {
t++;
v[xx][yy][tt] = 1;
a[t].x = xx, a[t].y = yy, a[t].t = tt, a[t].c = a[h].c + 1;
if (xx == tx && yy == ty && tt == 1) {
printf("%d\n", a[t].c);
return;
}
}
}
}
printf("Impossible\n");
}
int main() {
while (scanf("%d%d", &n, &m)) {
memset(v, 0, sizeof(v));
if (n == 0 && m == 0)
break;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) cin >> lyx[i][j];
flag = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (lyx[i][j] == 'O')
tx = i, ty = j;
if (lyx[i][j] == 'X' && !flag) {
a[1].x = i, a[1].y = j, flag = 1;
if (lyx[i][j + 1] == 'X')//状态2:横着躺着
a[1].t = 2;
else if (lyx[i + 1][j] == 'X')//状态3:竖着躺着
a[1].t = 3;
else
a[1].t = 1, v[i][j][a[i].t] = 1;//状态1:立着
}
}
}
bfs();
}
}