【POJ3322】Bloxorz I
一道非常棒的搜索题,做完之后感觉神清气爽……
可以肯定的是,本题属于走地图一类的搜索题,适合用bfs求解,然而本题细节极多,有很多需要注意的地方。
我们定义状态三元组(x,y,z)表示当前移动到位置(x,y),且朝向z(我们不妨假定z=0意味着长方体立在地面上,z=1 意味着长方体横躺,x,y表示左边长方体的位置;z=2意味着长方体竖躺,x,y表示上边长方体的位置)。同时,我们读入之后处理起点和终点,并加入队列。我们还要处理关于移动的常量数组(本题的关键),这样我们就可以进行bfs了,但是本题虽然思路简单,但是细节繁多,实现起来有一定难度。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using namespace std; 6 struct node { 7 int x,y,z; 8 }s,t; 9 queue<node> q; 10 int n,m,dis[510][510][4]; 11 char map[510][510]; 12 const int fx[4]={0,0,-1,1}; 13 const int fy[4]={-1,1,0,0}; 14 const int nx[3][4]={{0,0,-2,1},{0,0,-1,1},{0,0,-1,2}}; 15 const int ny[3][4]={{-2,1,0,0},{-1,2,0,0},{-1,1,0,0}}; 16 const int nz[3][4]={{1,1,2,2},{0,0,1,1},{2,2,0,0}}; 17 inline bool can(int x,int y) { 18 return x>=1&&x<=n&&y>=1&&y<=m; 19 } 20 inline bool can(node now) { 21 if(!can(now.x,now.y)) return 0; 22 if(map[now.x][now.y]=='#') return 0; 23 if(now.z==0&&map[now.x][now.y]!='.') return 0; 24 if(now.z==1&&map[now.x][now.y+1]=='#') return 0; 25 if(now.z==2&&map[now.x+1][now.y]=='#') return 0; 26 return 1; 27 } 28 void pre() { 29 for(int i=1;i<=n;i++) 30 for(int j=1;j<=m;j++) { 31 if(map[i][j]=='O') { 32 map[i][j]='.'; 33 t.x=i; t.y=j; t.z=0; 34 } 35 else if(map[i][j]=='X') { 36 for(int k=0;k<4;k++) { 37 int xx=i+fx[k]; 38 int yy=j+fy[k]; 39 if(can(xx,yy)&&map[xx][yy]=='X') { 40 s.x=min(i,xx); s.y=min(j,yy); 41 s.z=k<2?1:2; 42 map[xx][yy]=map[i][j]='.'; 43 break ; 44 } 45 } 46 if(map[i][j]=='X') s.x=i,s.y=j,s.z=0; 47 } 48 } 49 } 50 void bfs() { 51 dis[s.x][s.y][s.z]=0; 52 q.push(s); 53 while(!q.empty()) { 54 node now=q.front(); 55 q.pop(); 56 for(int i=0;i<4;i++) { 57 node neww; 58 neww.x=now.x+nx[now.z][i]; 59 neww.y=now.y+ny[now.z][i]; 60 neww.z=nz[now.z][i]; 61 if(!can(neww)) continue ; 62 if(dis[neww.x][neww.y][neww.z]==-1) { 63 dis[neww.x][neww.y][neww.z]=dis[now.x][now.y][now.z]+1; 64 q.push(neww); 65 if(neww.x==t.x&&neww.y==t.y&&neww.z==t.z) { 66 printf("%d\n",dis[neww.x][neww.y][neww.z]); 67 return ; 68 } 69 } 70 } 71 } 72 puts("Impossible"); 73 } 74 int main() { 75 while(cin>>n>>m&&n+m) { 76 for(int i=1;i<=n;i++) scanf("%s",map[i]+1); 77 pre(); 78 memset(dis,-1,sizeof(dis)); 79 while(!q.empty()) q.pop(); 80 bfs(); 81 } 82 return 0; 83 }