for2024蓝桥杯 NEFU OJ 558(深搜)

迷宫寻路-搜索

Problem:558                               Time Limit:1000ms                           Memory Limit:65536K
 

Description

AC小公主很喜欢设计迷宫,她设计的迷宫只有两个口,一个入口,一个出口。但小公主有时候很调皮,她会让挑战者走不出迷宫。现在给你AC小公主的迷宫请你判断挑战者能否成功从出口走出迷宫,迷宫包证边界为障碍物,只有两个不同的入口。
“#”代表障碍物,“*”代表可走的路。
 

Input

输入有多组,每组输入两个正整数n,m( 2 < n < m < 1000)。
接下来n行,每行有m个字符。

Output

每组测试实例,若挑战者能走出迷宫输出”YES”,否则输出“NO”。
 

Sample Input

3 3
#*#
#*#
#*#
3 3
#*#
###
#*#

Sample Output

YES
NO

错误

看到这道题的第一眼,我就想到了用深搜的方法来解决这道题。(其实,广搜也可以。)我第一想法是像最典型的深搜一样,找到一个“*”,然后分别从四个方向(上、下、左、右)一遍一遍地调用深搜函数,直到每个点都走了一次为止,最后检查这个二维数组还有没有“*”存在。如果有那就是走不出迷宫。后来我发现这样想是错的!!!大错特错!!!因为,这样想有一个前提是在这个迷宫里有且只有一条通路,且没有一个多余的点,且忽略了要从唯一一个入口进入。

正确思路

那么,这道题的正确思路是什么呢?通过题目我们可以知道:这个迷宫只有两个口,一个入口,一个出口。这点很重要哦!不要小瞧它。我们要做的第一步就是找到入口和出口,并把这两个点标记一下。这里我是采用遍历的方式,当一个点处在二维数组的边界(也就是横坐标为1或n,纵坐标为1或m时,这里我都是从1开始输入的),并且为“*”时,那它就是入口/出口,我分别用一个int类型的一维数组来记录下这个点的横、纵坐标。由题意知,我们一定会找到两个点,那么我们就令第一个找到的点为入口,第二个为出口。然后,我们从第一个点开始深搜。深搜的过程是,我们已经直到此时的点为“*”,那我们就马上把这个点变为“#”,代表我们走过了,然后往它的四个方向走,如果这个点满足在这个数组,并且为“*”的条件的话,我们就继续调用这个函数。就这样深搜结束后,因为我们之前标记过出口的坐标了,现在我们只要检查,经过这一次深搜后,出口点是不是由“*”变成了“#”。如果出口点已经变成了“#”,那就证明有这样一条路径,可以从入口走到出口;反之,则没有。

代码

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
char a[1005][1005];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int flag;
int strx[5],stry[5];
int n,m;
void dfs(int x,int y)
{
    a[x][y]='#';
    int x1,y1;
    for(int i=0;i<4;i++)
    {
        x1=x+dx[i];
        y1=y+dy[i];
        if(x1>=1&&x1<=n&&y1>=1&&y1<=m&&a[x1][y1]=='*')
        {
            dfs(x1,y1);
        }
    }
}
int main()
{
    while(cin>>n>>m)
    {
        flag=0;
        int p=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                cin>>a[i][j];
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if((i==1||i==n||j==1||j==m)&&a[i][j]=='*')//找到出入口
                {
                    strx[++p]=i;
                    stry[p]=j;
                }

            }
        }
        dfs(strx[1],stry[1]);
        if(a[strx[2]][stry[2]]=='#') flag=1;
        if(flag==1) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值