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\n", t);
            else printf("Case #%d: No\n", t);
        }
    }
    return 0;
}

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

扫描二维码关注公众号,回复: 10647936 查看本文章

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

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

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

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

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

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

if(nex.step>=8)

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

猜你喜欢

转载自www.cnblogs.com/heyour/p/12671362.html