這類題叫作圖的廣度優先遍歷題,不過給你的是隱式圖罷了(細節多)。node
考點就是隱式圖的遍歷(難度主要集中在判斷某節點是否與當前節點聯通這塊)。c++
#include<bits/stdc++.h> using namespace std; const int maxn=501; char a[maxn][maxn]; int n,m; int dx[4]={1,-1,0,0}; int dy[4]={0,0,1,-1}; struct node{int r,c,lie;}st,ed;//0: lizhe 1:shu tang 2:heng tang bool valid(int r,int c) { return r>=1&&r<=n&&c>=1&&c<=m; } bool valid(node v) { bool jd= a[v.r][v.c]!='#' && v.r>=1 && v.r<=n && v.c>=1 && v.c<=m; if(v.lie==0) { return a[v.r][v.c]!='E'&&jd; } if(v.lie==1) { return jd&&a[v.r+1][v.c]!='#' && v.r+1>=1 && v.r+1<=n && v.c>=1 && v.c<=m; } if(v.lie==2) { return jd&&a[v.r][v.c+1]!='#' && v.r>=1 && v.r<=n && v.c+1>=1 && v.c+1<=m; } } void findsted() { for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) { if(a[i][j]=='O') { ed.r=i,ed.c=j,ed.lie=0; a[i][j]='.'; } } int flag=0; for(int i=1;i<=n;++i) { if(flag) break; for(int j=1;j<=m;++j) { if(a[i][j]=='X') { st.r=i,st.c=j; for(int k=0;k<4;++k) { int x=i+dx[k],y=j+dy[k]; if(valid(x,y)&&a[x][y]=='X') { a[i][j]=a[x][y]='.'; if(k==0) { st.lie=1; } if(k==2) { st.lie=2; } flag=1; break; } } } if(a[i][j]=='X') { st.lie=0; a[i][j]='.'; flag=1;break; } } } } int r_move[3][4]={{-2,1,0,0},{-1,2,0,0},{0,0,1,-1}}; int c_move[3][4]={{0,0,-2,1},{0,0,-1,1},{-1,2,0,0}}; int lie_move[3][4]={{1,1,2,2},{0,0,1,1},{0,0,2,2}}; //move array int d[maxn][maxn][3]; int bfs() { memset(d,-1,sizeof d); d[st.r][st.c][st.lie]=0; queue<node>q; q.push(st); while(!q.empty()) { node u=q.front(); q.pop(); if(u.r==ed.r&&u.c==ed.c&&u.lie==ed.lie) return d[u.r][u.c][u.lie]; node v; for(int i=0;i<4;++i) { v.r=u.r+r_move[u.lie][i], v.c=u.c+c_move[u.lie][i], v.lie=lie_move[u.lie][i]; if(!valid(v)||d[v.r][v.c][v.lie]!=-1) continue; d[v.r][v.c][v.lie]=d[u.r][u.c][u.lie]+1; q.push(v); } } return -1; } int main() { while(scanf("%d%d",&n,&m)==2 && n) { for(int i=1;i<=n;++i) scanf("%s",a[i] + 1); findsted(); int ans=bfs(); if(ans==-1) printf("Impossible\n"); else printf("%d\n",ans); // printf("st(%d,%d,%d),ed(%d,%d,%d)\n",st.r,st.c,st.lie,ed.r,ed.c,ed.lie); } return 0; }