Bob的烦恼II 逃离迷宫

XTU热身赛出的题。本来这次比赛可以多些几道的,可惜脑袋浆糊掉了。。以后要更加努力,希望能超过师兄,师姐们啊。言归正传:

这道题首先一看,它就是一道搜索题。搜索题:一般无外乎两种方法 1、DFS。2、BFS。想了想DFS只要用一个标记pre[maxn][maxn]的数组记录前一个坐标的方向就行,如果和前面不同则step++。后来果断超时。于是想起了BFS,怎么去判断它是否转弯呢?一个方向搜到底,到底时换方向的时候拐弯数加一,那么出队再拓展路径的时候拐弯数肯定也要加一,因为与这个点在一条直线上的点已经全部入队了。于是就有了下面的代码: 

 

 

 #include <iostream>
 #include <queue>
 #include <cstdlib>
 #include <cstring>
 #include <cmath>
  #define MAX_LEN 101
  using  namespace std;
 
  struct node
 {
      int x,y;
      int step ;
 } in ,  out;
 
 queue <node> Q;
 
  const  int move[ 4][ 2] = {- 1, 00, 1 ,  1, 0 ,  0,- 1};
  int flag[MAX_LEN +  10][MAX_LEN +  10];          // 标记 
  char map[MAX_LEN +  10][MAX_LEN +  10];
  int n,m,bx,by,ex,ey,k;      // 入口坐标 
 
 
  void init()
 {
     memset(flag ,  false ,  sizeof(flag));
      while(!Q.empty()) Q.pop();
     memset(map ,  0 ,  sizeof(map));
 }
 
 
  bool Check( int x,  int y)
 {
      if(x >=  1 && x <= n && y >=  1 && y <= m && map[x][y] ==  ' . 'return  true;
      return  false;
 }
 
  void BFS()
 {
      if(bx == ex && by == ey)
     {
         printf( " yes\n ");
          return ;
     }
     
     flag[bx][by] =  true;
      in.x = bx;  in.y = by ;  in.step = - 1;
     Q.push( in);
      while(!Q.empty())
     {
          out = Q.front();
         Q.pop();
          int x =  out.x;
          int y =  out.y;
          for( int i =  0; i <  4 ; i++)
         {
              int xx = x + move[i][ 0];
              int yy = y + move[i][ 1];
              while(Check(xx , yy))
             {
                 if(flag[xx][yy] ==  false)
                {
                     flag[xx][yy] =  true;
                      in.x = xx;
                      in.y = yy;
                      in.step =  out.step+ 1;       // 转弯的次数
                     Q.push( in);
                      if( in.x == ex &&  in.y == ey &&  in.step <= k)
                      {
                             printf( " yes\n ");
                              return ;
                      }  // 如果找到
                 }
                 xx += move[i][ 0];
                 yy += move[i][ 1];
             }
         }
       }
     printf( " no\n ");
      return ;
 }
 
  int main()
 {
      int t;
      while(~scanf( " %d ", &t))
     {
          while(t--)
         {
             init();
             scanf( " %d %d ", &n , &m);
              for( int i =  1;i <= n; i++)
             {
                for( int j =  1 ; j <= m ;j++)
                   scanf( "  %c " , &map[i][j]);
             }
             
             scanf( " %d%d%d%d%d ", &k , &by , &bx , &ey , &ex);
             BFS();
         }
     }
      // system("pause");
      return  0;
 }

 

  这个题不一个方向搜到底肯定是错的,即使用优先队列把拐弯少的先出队来拓展路径也是不对的!

可以设想如果不把一个方向上的点先入队的话,那么有可能一个不需要拐弯的点在拓展时会被弄成要拐弯才能走到,这时候就不对了!

  一个方向搜到底,搜到底时换方向的时候拐弯数加一,那么出队再拓展路径的时候拐弯数肯定也要加一,因为与这个点在一条直线上的点已经全部入队了。

你可能感兴趣的:(BO)