/* 这题深搜和广搜都用到了 广搜比较简单 深搜的时候要注意是左优先还是右优先,还有就是当前的朝向(当前朝向的不同,导致对当前的左和右的方向不同) 对本代码来说:d1[4][2]={0,-1, -1,0, 0,1, 1,0}是左优先 ← ↑ → ↓ d1[4][2]={0,-1, -1,0, 0,1, 1,0} ↑用它可达到 →用它可以达到 ↓ 用它可以达到 ←用它可以达到 左转的目的,故 左转的目的,故 左转的目的,故 左转的目的,故 若朝向为↑,从 若朝向为→,从 若朝向为↓,从 若朝向为←,从 这儿开始 这儿开始 这儿开始 这儿开始 在dfs()中k都是从0开始的,要让不同朝向的从不同的地方开始,要对其朝向赋一定的值; 所以朝向↑=0;→=1;↓=2;←=3; 以上是对d1[][]左优先的做法,d2右优先同理可以分析出 */ #include<stdio.h> int w,h,sx,sy,ex,ey; struct node { int x,y; }; #include<queue> using namespace std; char map[45][45],vis[45][45]; int d1[4][2]={0,-1, -1,0, 0,1, 1,0},d2[4][2]={0,1, -1,0, 0,-1, 1,0}; int dfs(int i,int j,int to,int dir[][2])//i、j表示坐标,to朝向,dir[][]由调用函数传的转向数组 { int k,tem,xx,yy; if(i==ex&&j==ey) return 1; for(k=0;k<4;k++) { tem=(to+k)%4;//计算从哪里开始是他自己的左(右)优先 xx=i+dir[tem][0]; yy=j+dir[tem][1]; if(xx>=0&&xx<h&&yy>=0&&yy<w&&map[xx][yy]!='#')//一旦找到可行路线就向前走 break; } return dfs(xx,yy,(tem+3)%4,dir)+1;//由上面分析可知,转向后,他的朝向数减小1,故(tem+3)%4; } int bfs(int i,int j) { queue<node>q; node cur,next; cur.x=i; cur.y=j; int k; q.push(cur); memset(vis,0,sizeof(vis)); vis[i][j]=1; while(!q.empty()) { cur=q.front(); q.pop(); for(k=0;k<4;k++) { next.x=cur.x+d1[k][0]; next.y=cur.y+d1[k][1]; if(next.x>=0&&next.x<h&&next.y>=0&&next.y<w) { if(next.x==ex&&next.y==ey) return vis[cur.x][cur.y]+1; if(vis[next.x][next.y]==0&&map[next.x][next.y]!='#')//掉了后半截,老是不过 { vis[next.x][next.y]=vis[cur.x][cur.y]+1; q.push(next); } } } } } int main() { int t,i,j,da,db; scanf("%d",&t); while(t--) { scanf("%d%d",&w,&h); getchar(); for(i=0;i<h;i++) gets(map[i]); for(i=0;i<h;i++) for(j=0;j<w;j++) if(map[i][j]=='S') { sx=i; sy=j; } else if(map[i][j]=='E') { ex=i; ey=j; } map[sx][sy]='.'; map[ex][ey]='.'; if(sx==0)//赋左优先时的朝向数 da=2; else if(sx==(h-1)) da=0; else if(sy==0) da=1; else da=3; if(sx==0)//赋右优先时的朝向数 db=2; else if(sx==(h-1)) db=0; else if(sy==0) db=3; else db=1; int l=dfs(sx,sy,da,d1); int r=dfs(sx,sy,db,d2); int z=bfs(sx,sy); printf("%d %d %d\n",l,r,z); } return 0; }