zoukankan      html  css  js  c++  java
  • Problem B: DFS or BFS?

    Description

    说好了,题目不黑人。

    给你一个8*8的矩阵,你的初始位置是左下角方格(用'U’表示),你的目标位置是右上角的方格(用'A'表示),其余的62个方格,如果是'.',表示这个方格为空,如果是'S',表示这个方格有一块大石头。好了现在你开始从左下角出发,每次可以往上,下,左,右,左上,右上,左下,右下移动一个方格,或者你可以原地不动,一共九个动作方式,在你做完一个动作后,所有的大石头会往下掉一个方格(如果一个大石头的位置是(x,y),那下一秒是(x+1,y),不过如果它已经在最下面的一排了,那它就会掉出矩阵,不再出现),请注意,任一时刻,你不能和某一个大石头处在同一个方格,否则石头会把你XX掉。

    现在的问题就是:你能从左下角安全抵达右上角么? 如果能,输出“Yes”,反之,“No”。

    Input

    T->测试数据组数(T)。

    对于每组数据,输入一个8*8的矩阵,其后有一空行。描述如上。

    Output

    对于第i组数据,请输出

    Case #i: s(s是一个字符串,如果可以到达,则s为“Yes”,反之“No”)

    Sample Input

    2
    .......A
    ........
    ........
    ........
    ........
    ........
    ........
    U.......
    
    .......A
    ........
    ........
    ........
    ........
    .S......
    S.......
    US......
    

    Sample Output

    Case #1: Yes
    Case #2: No

    参考链接:(最详细解答) 问题 B: DFS or BFS?

    最终AC代码:

    #include <bits/stdc++.h>
    using namespace std; 
    bool flag;
    char mp[10][10];
    int dir[9][2]={{0,0},{-1,0},{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1}}; //方向 
    struct Node{
        int x, y, step;
    }now, nex;
    void BFS(){
        int i;
        queue<Node> q;
        now.x=7, now.y=0, now.step=0;
        q.push(now);
        while(!q.empty()){
            now = q.front();
            q.pop();
            for(i=0; i<9; i++){ //选择一个方向遍历 
                nex.x = now.x + dir[i][0];
                nex.y = now.y + dir[i][1];
                nex.step = now.step + 1;
                if(nex.x<0 || nex.x>=8 || nex.y<0 || nex.y>=8) continue; //位置不合法
                //下面的if判断很重要 上方有'S'则不可继续往这个方向走 上上方有'S'则往这个方向走后,会与'S'在同一位置 
                if(mp[nex.x-nex.step][nex.y]!='S' && mp[nex.x-nex.step+1][nex.y]!='S') {
                    if(mp[nex.x][nex.y]=='A' || nex.step>=8){ //达到'A'或步数达到8(所有'S'都掉光了) 
                        flag = true;
                        return ;
                    }
                    q.push(nex);
                }
            }
        }
    }
    int main(){
        int i, t, T;
        while(~scanf("%d", &T)){
            for(t=1; t<=T; t++){
                getchar(); //去掉多余的符号 
                for(i=0; i<8; i++) scanf("%s", mp[i]);
                flag = false;
                BFS();
                if(flag) printf("Case #%d: Yes
    ", t);
                else printf("Case #%d: No
    ", t);
            }
        }
        return 0;
    }

    比较疑惑的一点:nex.x-nex.step的结果是可能超过数组表示的范围的,即可能是负数。如果我在访问mp前面加上一个范围的判断nex.x-nex.step>=0,答案反而错了。这也就是说,不管加入队列q的Node的x坐标是多少,在没得到答案前,都得入队。

    其次的话,尝试了打印以下信息:

    //按如下形式访问 居然不会报错? 
    printf("====%c===%c===%c====
    ", mp[7][3], mp[-2][3], mp[12][3]);

    查了一下资料,如下:关于C++中数组下标越界不报错的问题

    可以理解为,这题使用广度优先遍历写,还得利用这个不做越界检查的性质?

    此外,值得注意的一点是,与以往BFS()遍历算法不同,此处入队前,并没有判断入队的点是否已经访问过。仔细想想,就会会感觉此题从另一个角度思考,可能会更容易理解:8x8的矩阵中,随机的分布了'S',并且每操作一步,那么'S'均往下掉一行,这不就等于在<8步内的操作避开'S'就可以输出答案'yes'了吗?

    所以找到答案的if判断其实可以简化成:

    if(nex.step>=8)

    虽然逻辑更简单了,但是这样的运算时间反而需要更多。。。。

  • 相关阅读:
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Siberia
    BZOJ5177 : [Jsoi2013]贪心的导游
    BZOJ1482 : [Balkan2017]Cats
    BZOJ5207 : [Jsoi2017]隧道
    XVIII Open Cup named after E.V. Pankratiev. Ukrainian Grand Prix
    线性代数笔记28——复矩阵和快速傅立叶变换
    闲话复数(2)——欧拉公式
    线性代数笔记27——对称矩阵及正定性
    闲话复数(1) | 不现实的虚数 i 为什么虚?它长成什么样?
    资源下载 | 深度学习、机器学习、机器学习实战、统计学习方法、高等数学、线性代数
  • 原文地址:https://www.cnblogs.com/heyour/p/12671362.html
Copyright © 2011-2022 走看看