poj 1475 || zoj 249 Pushing Boxes
http://poj.org/problem?id=1475
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=249
Pushing Boxes
Time Limit: 2000MS | Memory Limit: 131072K | |||
Total Submissions: 4662 | Accepted: 1608 | Special Judge |
Description
Imagine you are standing inside a two-dimensional maze composed of square cells which may or may not be filled with rock. You can move north, south, east or west one cell at a step. These moves are called walks.
One of the empty cells contains a box which can be moved to an adjacent free cell by standing next to the box and then moving in the direction of the box. Such a move is called a push. The box cannot be moved in any other way than by pushing, which means that if you push it into a corner you can never get it out of the corner again.
One of the empty cells is marked as the target cell. Your job is to bring the box to the target cell by a sequence of walks and pushes. As the box is very heavy, you would like to minimize the number of pushes. Can you write a program that will work out the best such sequence?
One of the empty cells contains a box which can be moved to an adjacent free cell by standing next to the box and then moving in the direction of the box. Such a move is called a push. The box cannot be moved in any other way than by pushing, which means that if you push it into a corner you can never get it out of the corner again.
One of the empty cells is marked as the target cell. Your job is to bring the box to the target cell by a sequence of walks and pushes. As the box is very heavy, you would like to minimize the number of pushes. Can you write a program that will work out the best such sequence?
Input
The input contains the descriptions of several mazes. Each maze description starts with a line containing two integers r and c (both <= 20) representing the number of rows and columns of the maze.
Following this are r lines each containing c characters. Each character describes one cell of the maze. A cell full of rock is indicated by a `#' and an empty cell is represented by a `.'. Your starting position is symbolized by `S', the starting position of the box by `B' and the target cell by `T'.
Input is terminated by two zeroes for r and c.
Following this are r lines each containing c characters. Each character describes one cell of the maze. A cell full of rock is indicated by a `#' and an empty cell is represented by a `.'. Your starting position is symbolized by `S', the starting position of the box by `B' and the target cell by `T'.
Input is terminated by two zeroes for r and c.
Output
For each maze in the input, first print the number of the maze, as shown in the sample output. Then, if it is impossible to bring the box to the target cell, print ``Impossible.''.
Otherwise, output a sequence that minimizes the number of pushes. If there is more than one such sequence, choose the one that minimizes the number of total moves (walks and pushes). If there is still more than one such sequence, any one is acceptable.
Print the sequence as a string of the characters N, S, E, W, n, s, e and w where uppercase letters stand for pushes, lowercase letters stand for walks and the different letters stand for the directions north, south, east and west.
Output a single blank line after each test case.
Otherwise, output a sequence that minimizes the number of pushes. If there is more than one such sequence, choose the one that minimizes the number of total moves (walks and pushes). If there is still more than one such sequence, any one is acceptable.
Print the sequence as a string of the characters N, S, E, W, n, s, e and w where uppercase letters stand for pushes, lowercase letters stand for walks and the different letters stand for the directions north, south, east and west.
Output a single blank line after each test case.
Sample Input
1 7 SB....T 1 7 SB..#.T 7 11 ########### #T##......# #.#.#..#### #....B....# #.######..# #.....S...# ########### 8 4 .... .##. .#.. .#.. .#.B .##S .... ###T 0 0
Sample Output
Maze #1 EEEEE Maze #2 Impossible. Maze #3 eennwwWWWWeeeeeesswwwwwwwnNN Maze #4 swwwnnnnnneeesssSSS
分析:
第一次看到题目的时候,以为可以两次bfs,先拿箱子bfs目标,记录路径,得到箱子的开始状态(即人的最终状态),然后再次拿人BFS箱子的初试状态,记录路径,把两个路径加起来即可(之前竟然不知道这个叫嵌套BFS)。
有几个细节需要注意:
1,箱子移动时,箱子可以移动到人当前所在的位置。
2,人移动时,人不能移动到箱子未改变状态时所在的位置。
后来第三组数据不对,想到了箱子是不能像人一样拐弯的,Orz
WA代码:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <iostream> 4 #include <string.h> 5 #include <string> 6 #include <math.h> 7 #include <stdlib.h> 8 #include <queue> 9 #include <stack> 10 #include <set> 11 #include <map> 12 #include <list> 13 #include <iomanip> 14 #include <vector> 15 #pragma comment(linker, "/STACK:1024000000,1024000000") 16 #pragma warning(disable:4786) 17 18 using namespace std; 19 20 const int INF = 0x3f3f3f3f; 21 const int MAX = 20 + 2; 22 const double eps = 1e-8; 23 const double PI = acos(-1.0); 24 25 char ma[MAX][MAX]; 26 int vis[MAX][MAX]; 27 int n , m; 28 int si , sj , bi , bj , ti , tj , ei , ej; 29 int dir[4][2] = {1 , 0 , -1 , 0 , 0 , 1 , 0 , -1}; 30 char path[4] = {'S' , 'N' , 'E' , 'W'}; 31 char path1[4] = {'s' , 'n' , 'e' , 'w'}; 32 string str , str1 , ans; 33 34 struct T 35 { 36 int x , y ; 37 string sss; 38 }temp , in , out; 39 40 queue<T>qq , qq1; 41 42 void bfs(int i , int j) 43 { 44 temp.x = i; 45 temp.y = j; 46 temp.sss = ""; 47 qq.push(temp); 48 vis[i][j] = 1; 49 while(!qq.empty()) 50 { 51 out = qq.front(); 52 qq.pop(); 53 if(out.x == ti && out.y == tj) 54 { 55 str = out.sss; 56 break; 57 } 58 for(int k = 0;k < 4;k ++) 59 { 60 int ix = out.x + dir[k][0]; 61 int iy = out.y + dir[k][1]; 62 if(ma[ix][iy] == '#' || vis[ix][iy] || ix < 1 || iy < 1 || ix > n || iy > m) 63 continue; 64 in.x = ix; 65 in.y = iy; 66 in.sss = out.sss + path[k]; 67 vis[ix][iy] = 1; 68 qq.push(in); 69 } 70 } 71 } 72 73 void bfs1(int i , int j) 74 { 75 temp.x = i; 76 temp.y = j; 77 temp.sss = ""; 78 qq.push(temp); 79 vis[i][j] = 1; 80 while(!qq.empty()) 81 { 82 out = qq.front(); 83 qq.pop(); 84 if(out.x == ei && out.y == ej) 85 { 86 str1 = out.sss; 87 break; 88 } 89 for(int k = 0;k < 4;k ++) 90 { 91 int ix = out.x + dir[k][0]; 92 int iy = out.y + dir[k][1]; 93 if(ma[ix][iy] == '#' || ma[ix][iy] == 'B' || vis[ix][iy] || ix < 1 || iy < 1 || ix > n || iy > m) 94 continue; 95 in.x = ix; 96 in.y = iy; 97 in.sss = out.sss + path1[k]; 98 vis[ix][iy] = 1; 99 qq.push(in); 100 } 101 } 102 } 103 104 int main() 105 { 106 int first = 1; 107 while(scanf("%d %d",&n , &m) , n + m) 108 { 109 int i , j; 110 memset(vis , 0 , sizeof(vis)); 111 for(i = 1;i <= n;i ++) 112 { 113 for(j = 1;j <= m;j ++) 114 { 115 scanf("%c",&ma[i][j]); 116 if(ma[i][j] == 'S') 117 { 118 si = i; 119 sj = j; 120 } 121 else if(ma[i][j] == 'B') 122 { 123 bi = i; 124 bj = j; 125 } 126 else if(ma[i][j] == 'T') 127 { 128 ti = i; 129 tj = j; 130 } 131 } 132 getchar(); 133 } 134 str = ""; 135 while(!qq.empty()) 136 qq.pop(); 137 bfs(bi , bj); 138 if(str[0] == 'S') 139 { 140 ei = bi - 1; 141 ej = bj; 142 } 143 else if(str[0] == 'N') 144 { 145 ei = bi + 1; 146 ej = bj; 147 } 148 else if(str[0] == 'E') 149 { 150 ei = bi; 151 ej = bj - 1; 152 } 153 else if(str[0] == 'W') 154 { 155 ei = bi; 156 ej = bj + 1; 157 } 158 159 memset(vis , 0 , sizeof(vis)); 160 str1 = ""; 161 while(!qq.empty()) 162 qq.pop(); 163 bfs1(si , sj); 164 ans = ""; 165 ans = str1 + str; 166 167 printf("Maze #%d\n",first ++); 168 if(ans != "") 169 cout << ans << "\n" << endl; 170 else 171 cout << "Impossible\n" << endl; 172 } 173 return 0; 174 }
后来搜了一些资料。
双重bfs:
在推箱子游戏中人推箱子只有两种情况:
人推箱子:那么箱子此时所处的位置就是人接下来会到达的位置
人找位子推箱子:那么人就要到达箱子下一步到达位子对应的相反方向得那一个格子
所以,主干是箱子的移动过程,箱子每移动一步就对接下来人所处的位子进行考虑。也就是在一次bfs的过程中不断套用另一个bfs
AC代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <string> 5 #include <queue> 6 using namespace std; 7 8 const int maxn = 22; 9 char map[maxn][maxn]; 10 bool visPerson[maxn][maxn]; 11 bool visBox[maxn][maxn]; 12 13 int R , C; 14 int dir[4][2] = { {0,1},{0,-1},{1,0},{-1,0} }; 15 char pushes[4] = { 'E','W','S','N' }; 16 char walks[4] = { 'e','w','s','n' }; 17 string path; 18 struct Node 19 { 20 int br , bc , pr , pc; 21 string ans; 22 }; 23 bool inMap(int r , int c) 24 { 25 return r>=0 && r<R && c>=0 && c<C; 26 } 27 bool bfs2(int sr, int sc, int er, int ec, int br, int bc, string &ans) 28 { 29 Node node , tmpnode; 30 memset(visPerson,0,sizeof(visPerson)); 31 queue<Node> Q; 32 node.pr = sr; 33 node.pc = sc; 34 node.ans = ""; 35 Q.push(node); 36 visPerson[br][bc] = true; 37 while(!Q.empty()) { 38 node = Q.front(); Q.pop(); 39 if(node.pr == er && node.pc == ec) { 40 ans = node.ans; 41 return true; 42 } 43 if(visPerson[node.pr][node.pc]) continue; 44 visPerson[node.pr][node.pc] = true; 45 for(int i=0;i<4;i++) { 46 int nr = node.pr + dir[i][0]; 47 int nc = node.pc + dir[i][1]; 48 if(inMap(nr,nc) && !visPerson[nr][nc] && map[nr][nc]!='#') { 49 tmpnode.pr = nr; 50 tmpnode.pc = nc; 51 tmpnode.ans =node.ans + walks[i]; 52 Q.push(tmpnode); 53 } 54 } 55 } 56 return false; 57 } 58 bool bfs1(int sr ,int sc, int br, int bc) { 59 Node node , tmpnode; 60 memset(visBox,0,sizeof(visBox)); 61 queue<Node> Q; 62 node.pr = sr; 63 node.pc = sc; 64 node.br = br; 65 node.bc = bc; 66 node.ans = ""; 67 Q.push(node); 68 while(!Q.empty()) { 69 node = Q.front(); Q.pop(); 70 if(visBox[node.br][node.bc]) 71 continue; 72 visBox[node.br][node.bc] = true; 73 if(map[node.br][node.bc]=='T') { 74 path = node.ans; 75 return true; 76 } 77 visBox[node.br][node.bc] = true; 78 for(int i=0;i<4;i++) { 79 int nextr = node.br + dir[i][0]; 80 int nextc = node.bc + dir[i][1]; 81 int backr = node.br - dir[i][0]; 82 int backc = node.bc - dir[i][1]; 83 string ans = ""; 84 if( inMap(nextr,nextc) && inMap(backr,backc) 85 && map[nextr][nextc]!='#' && map[backr][backc]!='#' 86 && !visBox[nextr][nextc] ) { 87 if(bfs2(node.pr, node.pc, backr, backc, node.br, node.bc, ans)) { 88 tmpnode.pr = node.br; 89 tmpnode.pc = node.bc; 90 tmpnode.br = nextr; 91 tmpnode.bc = nextc; 92 tmpnode.ans = node.ans +ans +pushes[i]; 93 Q.push(tmpnode); 94 } 95 } 96 } 97 } 98 return false; 99 } 100 int main() { 101 int cas = 1; 102 int sr , sc , br , bc; 103 while(~scanf("%d%d",&R,&C) && R) { 104 for(int i=0;i<R;i++) scanf("%s",map[i]); 105 for(int i=0;i<R;i++) 106 for(int j=0;j<C;j++) { 107 if(map[i][j]=='S') { 108 sr = i; sc = j; 109 } 110 if(map[i][j]=='B') { 111 br = i; bc = j; 112 } 113 } 114 path = ""; 115 printf("Maze #%d\n",cas++); 116 bfs1(sr,sc,br,bc) ? cout<<path<<endl : cout<<"Impossible."<<endl; 117 cout<<endl; 118 } 119 return 0; 120 }
后来测试了几组数据:发现有些数据过不了(比如下面的数据),oj数据水呀。
1 8 9 2 ######### 3 #......T# 4 #.S.....# 5 ##B###### 6 #.......# 7 #.......# 8 #.......# 9 #########
以箱子为开始点 进行BFS。每次判断人(BFS)能不能到达箱子所需推到的反方向。如果能救如队列。有几个细节需要注意。1,箱子移动时,箱子可以移动到人当前所在的位置。2,人移动时,人不能移动到箱子未改变状态时所在的位置。。然后模拟即可。
AC代码:
1 #include<iostream> 2 #include<vector> 3 #include<cstdio> 4 #include<string> 5 #include<queue> 6 #include<cstring> 7 using namespace std; 8 int n,m; 9 char map[25][25]; 10 int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; 11 int other_dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; 12 int ex,ey,flag; 13 bool vis[25][25][25][25]; 14 bool mark[25][25]; 15 char op[]="nswe"; 16 char big_op[]="NSWE"; 17 string ans; 18 struct node{ 19 int b_x,b_y; 20 int p_x,p_y; 21 int step; 22 string ans; 23 }s_pos; 24 bool cheack(int x,int y){ 25 return x>=0&&x<n&&y>=0&&y<m&&map[x][y]!='#'; 26 return false; 27 } 28 bool people_cango(node &cur,node last,int e_x,int e_y){ 29 queue<node > q; node per;per=cur; per.step=0; per.ans=""; 30 memset(mark,false,sizeof(mark)); 31 q.push(per); 32 mark[cur.p_x][cur.p_y]=true; 33 34 while(!q.empty()){ 35 node now=q.front(); q.pop(); 36 if(now.p_x==e_x&&now.p_y==e_y){ 37 cur.ans+=now.ans; 38 return true; 39 } 40 for(int i=0;i<4;i++){ 41 node next=now; next.step+=1; 42 next.p_x+=dir[i][0]; next.p_y+=dir[i][1]; 43 if(cheack(next.p_x,next.p_y)&&!mark[next.p_x][next.p_y]){ 44 if(next.p_x==last.b_x&&next.p_y==last.b_y) continue; //遇见箱子 45 mark[next.p_x][next.p_y]=true; 46 next.ans+=op[i]; 47 if(next.p_x==e_x&&next.p_y==e_y){ 48 cur.ans+=next.ans; 49 return true; 50 } 51 q.push(next); 52 } 53 } 54 } 55 return false; 56 57 } 58 void bfs(){ 59 queue<node > q; 60 memset(vis,false,sizeof(vis)); q.push(s_pos); 61 vis[s_pos.b_x][s_pos.b_y][s_pos.p_x][s_pos.p_y]=true; 62 while(!q.empty()){ 63 node now = q.front(); q.pop(); 64 65 for(int i=0;i<4;i++){ 66 node next = now; next.step+=1; 67 next.b_x+=dir[i][0]; next.b_y+=dir[i][1]; 68 69 int x=now.b_x+other_dir[i][0]; //人要到达箱子的反面 70 int y=now.b_y+other_dir[i][1]; 71 if(cheack(next.b_x,next.b_y)&&cheack(x,y)&&!vis[next.b_x][next.b_y] 72 [now.b_x][now.b_y]){ 73 // if(next.b_x==now.p_x&&next.b_y==now.p_y) continue; 74 // cout<<next.p_x<<" "<<next.p_y<<endl; 75 76 if(people_cango(next,now,x,y)){ 77 // cout<<x<<" "<<y<<endl; 78 next.p_x=now.b_x; 79 next.p_y=now.b_y; 80 next.ans+=big_op[i]; 81 if(next.b_x==ex&&next.b_y==ey){ 82 flag=1; 83 ans=next.ans; 84 return ; 85 } 86 87 vis[next.b_x][next.b_y][next.p_x][next.p_y]=true; 88 q.push(next); 89 } 90 } 91 92 93 } 94 95 } 96 97 } 98 int main(){ 99 int ca=1; 100 while(scanf("%d%d",&n,&m)!=EOF,n+m){ 101 102 for(int i=0;i<n;i++) scanf("%s",map[i]); 103 104 for(int i=0;i<n;i++){ 105 for(int j=0;j<m;j++){ 106 if(map[i][j]=='T'){ 107 ex=i,ey=j; 108 } 109 if(map[i][j]=='B'){ 110 s_pos.b_x=i; s_pos.b_y=j; 111 } 112 if(map[i][j]=='S'){ 113 s_pos.p_x=i; s_pos.p_y=j; 114 } 115 } 116 } 117 118 119 flag=0; s_pos.step=0; s_pos.ans=""; 120 bfs(); 121 cout<<"Maze #"<<ca++<<endl; 122 if(flag){ 123 cout<<ans<<endl; 124 } 125 else 126 cout<<"Impossible."<<endl; 127 cout<<endl; 128 129 130 } 131 return 0; 132 }
AC代码:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <queue> 6 #include <string> 7 8 using namespace std; 9 10 #define MAXN 22 11 char P[4]={'N','S','W','E'}; 12 char M[4]={'n','s','w','e'}; 13 int R,C; 14 int dir[4][2]={-1,0,1,0,0,-1,0,1}; 15 char map[MAXN][MAXN]; 16 struct point 17 { 18 int x,y; 19 int p_x,p_y;//当前状态person所在的地方 20 string ans; 21 }; 22 bool isok(int x,int y) 23 { 24 if(x>=0 && x<R && y>=0 && y<C && map[x][y] != '#') 25 return true; 26 return false; 27 } 28 string tmp; 29 bool bfs_person(point en,point cu) 30 { 31 tmp=""; 32 point st; 33 st.x=en.p_x; 34 st.y=en.p_y; 35 st.ans=""; 36 queue<point>q; 37 bool vis[MAXN][MAXN]; 38 memset(vis,0,sizeof(vis)); 39 while(!q.empty()) 40 q.pop(); 41 q.push(st); 42 while(!q.empty()) 43 { 44 point cur,next; 45 cur=q.front(); 46 q.pop(); 47 if(cur.x==en.x && cur.y==en.y) 48 { 49 tmp=cur.ans; 50 return true; 51 } 52 for(int i=0;i<4;i++) 53 { 54 next=cur; 55 next.x=cur.x+dir[i][0]; 56 next.y=cur.y+dir[i][1]; 57 if(!isok(next.x,next.y)) continue; 58 if(next.x==cu.x && next.y==cu.y) continue; 59 if(vis[next.x][next.y]) continue; 60 vis[next.x][next.y]=1; 61 next.ans=cur.ans+M[i]; 62 q.push(next); 63 } 64 } 65 return false; 66 } 67 string bfs_box() 68 { 69 bool vis[MAXN][MAXN][4];//某点四个方向是否访问!!0==N,1==S,2==W,3==E 70 point st; 71 st.x=st.y=-1; 72 st.p_x=st.p_y=-1; 73 st.ans=""; 74 for(int i=0;i<R && (st.x==-1 || st.p_x==-1);i++) 75 for(int j=0;j<C && (st.x==-1 || st.p_x==-1);j++) 76 if(map[i][j]=='B') 77 { 78 st.x=i; 79 st.y=j; 80 map[i][j]='.'; 81 } 82 else if(map[i][j]=='S') 83 { 84 st.p_x=i; 85 st.p_y=j; 86 map[i][j]='.'; 87 } 88 //---------------------------------------- 89 //cout<<"st.x="<<st.x<<" st.y="<<st.y<<" st.p_x="<<st.p_x<<" st.p_y="<<st.p_y<<endl; 90 //---------------------------------------- 91 queue<point> q; 92 while(!q.empty()) 93 q.pop(); 94 q.push(st); 95 memset(vis,0,sizeof(vis)); 96 while(!q.empty()) 97 { 98 point cur=q.front();q.pop(); 99 //---------------------------------------- 100 // cout<<"cur.x="<<cur.x<<" cur.y="<<cur.y<<" cur.p_x="<<cur.p_x<<" cur.p_y="<<cur.p_y<<endl; 101 // cout<<"-----------------------------\n"; 102 //---------------------------------------- 103 point next,pre; 104 if(map[cur.x][cur.y]=='T') 105 return cur.ans; 106 for(int i=0;i<4;i++) 107 { 108 next=cur; 109 next.x=cur.x+dir[i][0]; 110 next.y=cur.y+dir[i][1]; 111 if(!isok(next.x,next.y)) 112 continue; 113 if(vis[next.x][next.y][i]) 114 continue; 115 pre=cur; 116 switch(i) 117 { 118 case 0: pre.x=cur.x+1;break; 119 case 1: pre.x=cur.x-1;break; 120 case 2: pre.y=cur.y+1;break; 121 case 3: pre.y=cur.y-1;break; 122 } 123 if(!bfs_person(pre,cur))//搜寻人是否能走到特定的位置 124 continue; 125 vis[next.x][next.y][i]=1; 126 next.ans=cur.ans+tmp; 127 next.ans=next.ans+P[i]; 128 next.p_x=cur.x;next.p_y=cur.y; 129 q.push(next); 130 } 131 } 132 return "Impossible."; 133 } 134 135 int main() 136 { 137 int cas=1; 138 while(scanf("%d%d",&R,&C) && (R+C)) 139 { 140 getchar(); 141 for(int i=0;i<R;i++) 142 gets(map[i]); 143 144 //--------------------------------------- 145 // for(int i=0;i<R;i++) 146 // cout<<map[i]<<endl; 147 //---------------------------------------- 148 149 printf("Maze #%d\n",cas++); 150 //printf("%s\n",bfs_box()); 151 cout<<bfs_box()<<endl<<endl; 152 } 153 return 0; 154 }
程序终究是会有bug,上面两个肯定也有bug数据过不了,就不列举啦,重要是思想。
下面一个是wcg的AC代码:
附上链接:http://www.cnblogs.com/lovychen/p/4453147.html
1 //解题思路:先判断盒子的四周是不是有空位,如果有,则判断人是否能到达盒子的那一边,能的话,把盒子推到空位处,然后继续 2 #include<iostream> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cstring> 6 #include<queue> 7 #include<string> 8 #include<cmath> 9 using namespace std; 10 int bx,by,sx,sy,tx,ty; 11 int m,n,dir[][2]={-1,0,1,0,0,-1,0,1};//注意题目要求的是n、s、w、e的顺序,因为这个wa了一次 12 char op[]={'n','s','w','e'}; 13 bool mark[25][25][4];//标记箱子四周的位置时候已被用过 14 int vis[25][25];//标记人走过的位置 15 char map[25][25]; 16 struct BB//盒子 17 { 18 int x,y,SX,SY;//SX,SY表示当前箱子固定了,人所在的位置 19 string ans; 20 }bnow,beed; 21 struct YY//人 22 { 23 int x,y; 24 string ans; 25 }ynow,yeed; 26 char up(char c) 27 { 28 return (c-'a'+'A'); 29 } 30 //aa,bb 表示当前盒子的位置;ss,ee表示起点; 31 bool bfs2(int s,int e,int aa,int bb,int ss,int ee)//寻找当前人,是否能够到达盒子指定的位置; 32 { 33 queue<YY>yy; 34 if(s<0 || s>m || e<0 || e>n || map[s][e] == '#') return false; 35 ynow.x = ss; ynow.y = ee; ynow.ans=""; 36 memset(vis,0,sizeof(vis)); 37 vis[aa][bb] =1;//不能经过盒子 38 vis[ss][ee] = 1;//起点标记为 39 yy.push(ynow); 40 while(!yy.empty()) 41 { 42 ynow = yy.front(); 43 yy.pop(); 44 if(ynow.x == s && ynow.y == e) 45 { 46 return true; 47 } 48 for(int i=0;i<4;i++) 49 { 50 yeed.x = ynow.x+dir[i][0]; 51 yeed.y = ynow.y+dir[i][1]; 52 if(yeed.x>0 && yeed.x<=m && yeed.y>0 && yeed.y<=n && !vis[yeed.x][yeed.y] && map[yeed.x][yeed.y]!='#') 53 { 54 yeed.ans = ynow.ans+op[i];//记录走过的路径 55 vis[yeed.x][yeed.y] = 1; 56 yy.push(yeed); 57 } 58 } 59 } 60 return false; 61 } 62 63 bool bfs1() 64 { 65 queue<BB>bb; 66 bnow.x = bx;bnow.y=by;bnow.ans=""; 67 bnow.SX = sx;bnow.SY=sy; 68 bb.push(bnow); 69 while(!bb.empty()) 70 { 71 72 bnow=bb.front(); 73 bb.pop(); 74 if(bnow.x == tx && bnow.y==ty) 75 { 76 return true; 77 } 78 for(int i=0;i<4;i++) //盒子周围的四个方向; 79 { 80 beed.x = bnow.x+dir[i][0]; 81 beed.y = bnow.y+dir[i][1]; 82 if(beed.x>0 && beed.x<=m && beed.y>0 && beed.y<=n && !mark[beed.x][beed.y][i] && map[beed.x][beed.y]!='#') 83 { 84 if(bfs2(beed.x-2*dir[i][0],beed.y-2*dir[i][1],bnow.x,bnow.y,bnow.SX,bnow.SY))//如果能推到yeed,则需要判断人是否能到达,它的上一个点; 85 { 86 beed.SX = bnow.x;//推完箱子后,人的位置在箱子上 87 beed.SY = bnow.y; 88 beed.ans=bnow.ans+ynow.ans+up(op[i]);//当前的加上推箱子的加上目前挨着推的; 89 mark[beed.x][beed.y][i] = true; 90 bb.push(beed); 91 } 92 } 93 } 94 } 95 return false; 96 } 97 98 int main() 99 { 100 int T,k=1; 101 while(scanf("%d %d",&m,&n) && m+n) 102 { 103 memset(mark,false,sizeof(mark)); 104 for(int i=1;i<=m;i++) 105 for(int j=1;j<=n;j++) 106 { 107 scanf(" %c",&map[i][j]); 108 if(map[i][j] == 'S') 109 { 110 sx=i;sy =j; 111 } 112 if(map[i][j] == 'T') 113 { 114 tx = i;ty = j; 115 } 116 if(map[i][j] == 'B') 117 { 118 bx = i;by = j; 119 } 120 } 121 printf("Maze #%d\n",k++); 122 if(bfs1()) 123 printf("%s\n\n",bnow.ans.c_str());//少个换行wa了一次 124 else 125 printf("Impossible.\n\n"); 126 } 127 return 0; 128 }
悠游天地间 all rights reserved. © 2013 -- 1 << 64