洛谷 AT1350 深さ優先探索
洛谷 AT1350 深さ優先探索
题意翻译
高桥先生住的小区是长方形的,被划分成一个个格子。高桥先生想从家里去鱼店,高桥先生每次可以走到他前后左右四个格子中的其中一个,但不能斜着走,也不能走出小区。
现在给出地图:
s
:代表高桥先生的家
g
:代表鱼店
.
:代表道路
#
:代表墙壁
高桥先生不能穿过墙壁。
输入:第一行输入n(1<=n<=500),m(1<=m<=500)代表小区的长和宽,接下来n行每行m个字符,描述小区中的每个格子。
输出:如果高桥先生能到达鱼店,输出"Yes",否则输出"No"。
输入输出样例
输入 #1复制
输出 #1复制
输入 #2复制
输出 #2复制
输入 #3复制
输出 #3复制
输入 #4复制
输出 #4复制
输入 #5复制
输出 #5复制
题解:
应该算是深搜的常用应用——地图遍历的模板题。
地图遍历是本蒟蒻自己起的名字。代表一类比较常见的题目,类似于走迷宫,是对矩阵的一种遍历方式。这种题型基本就是使用搜索(深搜和广搜只是实现方式不一样,最终达到的目的是一样的)来解决。那么这篇题解就细致地讲一下做这种题的思路和深搜的基本实现方式。
首先深搜的定义大家应该都有所了解。但是这种定义方式是基于树和图的深度优先遍历的,比较容易被大家理解。所以应该有好多小伙伴都是像本蒟蒻一样蒙圈:这种题无图无树,和深搜有关系么?
这就需要一个思维转换:构建搜索树。
所谓搜索树,就是把乍一看没法用深搜解决的问题抽象成一棵树,不是说深搜是对树和图的深度优先遍历么?那我把这个问题变成一个图,不就解决了么?
那好,我们开始抽象:
一张地图,对于每一个点(就是矩阵的每一个坐标),它有四个选择可走:上下左右。那么,我们可以将其抽象成一个每个节点有四个子节点的图。(当然,边界节点和墙都是除外的)
有了这个思路,就可以进行深搜了。
思路如下:输入矩阵,标记起始点。
从起点开始深搜,利用方向数组和判断,搜索整个图,在可到达点打上标记。
如果终点带标记,就输出是,否则就是否。
满分代码:(一个不大不小的细节:注意字符的读入,这里用的是cin,用scanf不一定读得进来)
#include<cstdio>
#include<iostream>
using namespace std;
const int maxn=510;
int n,m;
char map[maxn][maxn];
bool v[maxn][maxn];
int dx[]={0,0,0,-1,1};
int dy[]={0,1,-1,0,0};
int a,b,c,d;
void dfs(int x,int y)
{
v[x][y]=1;
for(int i=1;i<=4;i++)
{
int xx=x+dx[i];
int yy=y+dy[i];
if(xx<1 || xx>n || yy<1 || yy>m || map[xx][yy]=='#' || v[xx][yy])
continue;
dfs(xx,yy);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>map[i][j];
if(map[i][j]=='s')
a=i,b=j;
if(map[i][j]=='g')
c=i,d=j;
}
dfs(a,b);
if(v[c][d])
{
printf("Yes");
return 0;
}
else
{
printf("No");
return 0;
}
}