【题意】:在一个迷宫里,有一个人,还有一个出口。这里有四种操作:1.人向左走 2.人向右走 3.把整个迷宫向左转 4.把整个迷宫向右转。每操作一次都会花费一个时间单位。问人最后能否走出迷宫?如果能,输出最短的时间。

【题解】:看到最短时间,我们很容易就想到bfs。这题与平时的迷宫问题有一个不同的地方就是,平时题目所给的迷宫是俯视图,而这里是主视图,考虑到这一点,我们就要把重力加入我们的思考范围。简单点来说就是,如果当前这个人向左走了一步,而那个位置是没有站块的,那么人就会向下跌,直到有东西顶住为止。实际操作的时候可以固定迷宫不动,而是通过人来旋转,这显然是可以的。一开始我们可以预处理一下对于每个格转动之后人会跌在哪里,这样我们以后就可以用O(1)的时间来找到下一个状态。其余的操作跟普通bfs一样。

【代码】:
 1 #include "iostream"
 2 #include "queue"
 3 #include "cstdio"
 4 using namespace std;
 5 #define MAX 505
 6 struct node {
 7     int x, y, dir;
 8     void init(int a, int b, int c) {
 9         x = a, y = b, dir = c;
10     }
11 }rot[MAX][MAX][4], s;
12 int n, m;
13 int ti[MAX][MAX][4];
14 char maz[MAX][MAX];
15 const int dx[4= {10-10};
16 const int dy[4= {010-1};
17 
18 bool check(int i, int j) {
19     if(i >= 1 && i <= n && j >= 1 && j <= m) return true;
20     return false;
21 }
22 
23 int bfs() {
24     queue<node> que;
25     que.push(s);
26     ti[s.x][s.y][s.dir] = 1;
27     while(!que.empty()) {
28         node now = que.front(), next;
29         que.pop();
30         if(maz[now.x][now.y] == 'E'return ti[now.x][now.y][now.dir];
31         for(int i = 0; i < 4; i++) {
32             if((now.dir % 2 == 0 && i % 2 != 0|| (now.dir % 2 != 0 && i % 2 == 0)) {
33                 if(maz[now.x+dx[i]][now.y+dy[i]] != '#') {
34                     next = rot[now.x+dx[i]][now.y+dy[i]][now.dir];
35                     if(!ti[next.x][next.y][next.dir]) {
36                         ti[next.x][next.y][next.dir] = ti[now.x][now.y][now.dir] + 1;
37                         que.push(next);
38                     }
39                 }
40             }
41             if(i % 2) {
42                 next = rot[now.x][now.y][(now.dir + i) % 4];
43                 if(!ti[next.x][next.y][next.dir]) {
44                     ti[next.x][next.y][next.dir] = ti[now.x][now.y][now.dir] + 1;
45                     que.push(next);
46                 }
47             }
48         }
49     }
50     return 0;
51 }
52 
53 void init() {
54     for(int i = n; i; i--)
55         for(int j = m; j; j--)
56             if(maz[i][j] != '#') {
57                 if(check(i + 1, j) && maz[i+1][j] != '#') rot[i][j][0= rot[i+1][j][0];
58                 else rot[i][j][0].init(i, j, 0);
59                 if(check(i, j + 1&& maz[i][j+1!= '#') rot[i][j][3= rot[i][j+1][3];
60                 else rot[i][j][3].init(i, j, 3);
61             }
62     for(int i = 1; i <= n; i++)
63         for(int j = 1; j <= m; j++)
64             if(maz[i][j] != '#') {
65                 if(check(i - 1, j) && maz[i-1][j] != '#') rot[i][j][2= rot[i-1][j][2];
66                 else rot[i][j][2].init(i, j, 2);
67                 if(check(i, j - 1&& maz[i][j-1!= '#') rot[i][j][1= rot[i][j-1][1];
68                 else rot[i][j][1].init(i, j, 1);
69             }
70 }
71 
72 int main() {
73     while(~scanf("%d%d"&n, &m)) {
74         getchar();
75         for(int i = 1; i <= n; i++)
76             for(int j = 1; j <= m + 1; j++) {
77                 for(int k = 0; k < 4; k++) ti[i][j][k] = 0;
78                 scanf("%c"&maz[i][j]);
79                 if(maz[i][j] == '|') s.init(i, j, 0);
80             }
81         init();
82         int ans = bfs();
83         if(!ans) printf("Can not escape!\n");
84         else printf("%d\n", ans - 1);
85     }
86     return 0;
87 }