zoukankan      html  css  js  c++  java
  • 杭电 逃离迷宫 BFS

      给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?

    Input  第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中, 
      第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x 1, y 1, x 2, y 2 (1 ≤ k ≤ 10, 1 ≤ x1, x 2 ≤ n, 1 ≤ y 1, y 2 ≤ m),其中k表示gloria最多能转的弯数,(x 1, y 1), (x 2, y2)表示两个位置,其中x 1,x 2对应列,y 1, y 2对应行。 
    Output  每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。Sample Input

    2
    5 5
    ...**
    *.**.
    .....
    .....
    *....
    1 1 1 1 3
    5 5
    ...**
    *.**.
    .....
    .....
    *....
    2 1 1 1 3

    Sample Output

    no
    yes
    这个题目在搜索题目中应该是一个比较难的题目了,做法就是讲BFS当DFS用
    传统的BFS一般情况下用来计算从一个点到另外一个点的最短路径之类的问题,但是这个题目让求最短的转弯次数,思路就是 沿着一个方向一致走 ,我遍历完该方向的所有点,当与到终点是直接输出转弯次数。
    AC代码:
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    struct stu{
        int a,b,c;//分别指点的坐标与当前转弯次数
    }e1,e2,e3;
    int d[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//四个方向,一定要对四个方向中,沿着每一个方向走,, 直到撞墙
    int mark[100+10][100+10]; 
    char arr[100+10][100+10];
    int n,m;
    int k,x1,y1,x2,y2;
    
    
    int bfs(){
        queue<stu>que;
        que.push({x1,y1,-1});//初始转弯为-1,因为第一次转弯不计数
        mark[x1][y1]=1;//初识标记 
        
        while(que.size()){
            int xx=que.front().a;
            int yy=que.front().b;
            int zz=que.front().c;
            que.pop();
            if(zz>=k) break;//这里为什么直接跳出呢,因为我们用bfs队列中存储的都是最少的转弯次数,如果转弯次数为k但是没有到终点,以后的转弯次数只会越来越来大,所以要跳出
            
            for(int i=0;i<4;i++){
                int dx=xx+d[i][0];
                int dy=yy+d[i][1];
                int cnt=zz+1;//转弯次数加一,每一个方向Zz是不变的,,所以在每个方向cnt是相等的
                while(1){//一直走
                    if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&arr[dx][dy]=='.')//判断越界等
                    {
                        if(dx==x2&&dy==y2)//终点直接输出,,不用判断转弯次数,因为我们前边加了个if(zz>=k) break;所以cnt最大为k
                        {
                            return 1;
                        }
                        if(mark[dx][dy]==0){
                            mark[dx][dy]=1;
                            que.push({dx,dy,cnt});
                        }
                        dx=dx+d[i][0];//因为一直沿着i这个方向走,所以只改变dx与dy的值就好了
                        dy=dy+d[i][1];
                    }
                    else break;
                }
            }
        }
        return 0;
    }
    
    
    int main()
    {
        int t;
        cin>>t;
        while(t--){
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++){
                    cin>>arr[i][j];    
                }
            scanf("%d%d%d%d%d",&k,&y1,&x1,&y2,&x2);
            memset(mark,0,sizeof(mark));
            if(bfs())
                 puts("yes");
            else puts("no");
        }
        return 0;
     } 


  • 相关阅读:
    elasticsearch 事务日志 sync 都干了些什么?
    elasticsearch 事务日志是个啥东西?
    elasticsearch 分片恢复经历了哪些步骤?
    定向爬取网页内容
    文件查询之三:文件和目录的批量操作
    文件查询之二:文件属性查询
    文件查询之一:文件名和文件后缀查询
    记一次SQL联合查询注入工具的编写
    线程间使用socket通信的计算器
    简单的远程加解密文件
  • 原文地址:https://www.cnblogs.com/Accepting/p/11253501.html
Copyright © 2011-2022 走看看