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;
 }

 

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

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

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

posted on 2012-05-20 15:01  有间博客  阅读(204)  评论(0编辑  收藏  举报