比较简单的搜索题,用到了dfs和bfs。dfs比较适合搜索有无可行解,如本题中左转优先和右转优先是利用dfs算法求解得,而bfs适合寻找最优解,如本题最短路径就是bfs。
这道题有一个比较需要注意的地方就是bfs时用visit[][]记录是否访问时,一定要在加入que队列的时候就修改visit[x][y]的值,我第一次是在出队列的时候修改其值,因为想的是出队列时才是访问它的时候,但是这样就大错特错了!!RE了好久,真是伤不起。。。一定要在加入que时就修改visit!!
下面贴代码。
#include<iostream> using namespace std; char maze[41][41]; int nextmove[4][2]={0,1,1,0,0,-1,-1,0}; //方向分别是东、南、西、北 int lcount,rcount; char visit[41][41]; void left(int x,int y,int dir,int w,int h){ lcount++; if (maze[x][y]=='E') return; int ndir,nx,ny; for (int i=3;i<=6;i++){ //左转和右转先后次序是不一样的! ndir=(dir+i)%4; nx=x+nextmove[(dir+i)%4][0]; ny=y+nextmove[(dir+i)%4][1]; if (nx>=0 &&nx<h&&ny>=0&&ny<w&&maze[nx][ny]!='#') {break;} } left(nx,ny,ndir,w,h); } void right(int x,int y,int dir,int w,int h){ rcount++; if (maze[x][y]=='E') return; int ndir,nx,ny; for (int i=5;i>=2;i--){ //右转优先,注意和left函数中的区别! ndir=(dir+i)%4; nx=x+nextmove[(dir+i)%4][0]; ny=y+nextmove[(dir+i)%4][1]; if (nx>=0 &&nx<h&&ny>=0&&ny<w&&maze[nx][ny]!='#') {break;} } right(nx,ny,ndir,w,h); } int que[1650][2]; void shortBFS(int sx,int sy,int w,int h){ int front=0,rear=0,step=0,flag=0; memset(visit,'0',sizeof(visit)); que[rear][0]=sx; que[rear++][1]=sy; visit[sx][sy]='1'; while(front<rear&&!flag){ int tmp=rear; step++; while (front<tmp){ int cx=que[front][0]; int cy=que[front++][1]; if (maze[cx][cy]=='E'){cout<<step<<endl;flag=1;break;} int nx,ny; for (int i=0;i<4;i++){ nx=cx+nextmove[i][0]; ny=cy+nextmove[i][1]; if (nx>=0 &&nx<h&&ny>=0&&ny<w&&maze[nx][ny]!='#'&&visit[nx][ny]!='1') { que[rear][0]=nx; que[rear++][1]=ny; visit[nx][ny]='1'; //一定要在这里就修改visit! } } } } } int main(){ int cases; cin>>cases; while(cases--){ lcount=rcount=0; int w,h; cin>>w>>h; memset(maze,' ',sizeof(maze)); for (int i=0;i<h;i++){ cin>>maze[i]; } int lax=-1,lay=-1; for (int i=0;i<h;i++){ for (int j=0;j<w;j++){ if (maze[i][j]=='S'){ lax=i; lay=j; break; } } } left(lax,lay,0,w,h); cout<<lcount<<" "; right(lax,lay,0,w,h); cout<<rcount<<" "; shortBFS(lax,lay,w,h); } return 0; }