Problem B: DFS or BFS? 广度优先搜索应用

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 Copy

2
.......A
........
........
........
........
........
........
U.......

.......A
........
........
........
........
.S......
S.......
US......

Sample Output Copy

Case #1: Yes
Case #2: No

思路

  • 本题使用bfs,需要一个队列来push和pop点从而走迷宫,详情请见bfs相关知识
  • 注意使用states(set)来判断是否该坐标和当时的bottom的值是否曾经出现过
    • 因为bfs是不断push和pop来保存状态的
    • 所以可能造成到达某一层的A点和B点继续运动后会同时到达C点,状况重复
  • 与过去的bfs不同的是,本题有每动一次,石头集体下落一格的特殊要求
    • 如果遍历整个map,会造成非常大的时间复杂度
    • 所以比起修改整体的地图,更好的选择是切换视角
    • 也就是top[2]所做的工作,同时top[2]可以保证点向上运动的趋势,从而快速达到最终点
  • 当达到最上面一行时,一定可以到达终点(只要向左一直走就好),直接return。

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <set>
#include <queue>
using namespace std;

char map[8][8];
set<vector<int>> states;//用set判断人物移动后,坐标和bottom的值是否曾经出现过

int flag;

struct point{
    
    
    int x;
    int y;
    int step;
};

bool check(int x,int y,int bottom){
    
    
    //注意判断其上方是否是一个石头
    if(x>=0&&x<=bottom&&y>=0&&y<8&&map[x][y]!='S'&&map[x-1][y]!='S')
        return true;
    return false;
}

void bfs(){
    
    
    states.clear();
    states.insert({
    
    7,0,7});//插入起始点
    queue<vector<int>> Q;//bfs队列
    Q.push({
    
    7,0,7});//插入起始点
    while(!Q.empty()){
    
    //队列为空,bfs结束
        vector<int> top=Q.front();
        if(top[2]==0||top[0]==0){
    
    
            //代表到达最上面一行以上,则安全
            flag=true;
            return;
        }
        Q.pop();//弹出,开始处理
        for(int i=-1;i<=1;i++){
    
    
            for(int j=-1;j<=1;j++){
    
    
                if(check(top[0]+i,top[1]+j,top[2])&&!states.count({
    
    top[0]+i-1,top[1]+j,top[2]-1})){
    
    
                    states.insert({
    
    top[0]+i-1,top[1]+j,top[2]-1});//插入新点
                    Q.push({
    
    top[0]+i-1,top[1]+j,top[2]-1});
                }
            }
        }
    }
}

int main(){
    
    
    int n=0;
    while(scanf("%d",&n)!=EOF){
    
    
        for(int k=1;k<=n;k++){
    
    
            flag=false;
            string input;
            getline(cin,input);
            for(int i=0;i<8;i++){
    
    
                getline(cin,input);
                for(int j=0;j<8;j++){
    
    
                    map[i][j]=input[j];
                }
            }
            bfs();
            printf("Case #%d: %s\n", k, flag ? "Yes" : "No");
        }
        
    }
    return 0;

猜你喜欢

转载自blog.csdn.net/Cindy_00/article/details/109283339