ACwing1112(DFS问题)
一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由 n∗nn∗n 的格点组成,每个格点只有2种状态,.
和#
,前者表示可以通行后者表示不能通行。
同时当Extense处在某个格点时,他只能移动到东南西北(或者说上下左右)四个方向之一的相邻格点上,Extense想要从点A走到点B,问在不走出迷宫的情况下能不能办到。
如果起点或者终点有一个不能通行(为#),则看成无法办到。
注意:A、B不一定是两个不同的点。
输入格式
第1行是测试数据的组数 kk,后面跟着 kk 组输入。
每组测试数据的第1行是一个正整数 nn,表示迷宫的规模是 n∗nn∗n 的。
接下来是一个 n∗nn∗n 的矩阵,矩阵中的元素为.
或者#
。
再接下来一行是 4 个整数 ha,la,hb,lbha,la,hb,lb,描述 AA 处在第 haha 行, 第 lala 列,BB 处在第 hbhb 行, 第 lblb 列。
注意到 ha,la,hb,lbha,la,hb,lb 全部是从 0 开始计数的。
输出格式
k行,每行输出对应一个输入。
能办到则输出“YES”,否则输出“NO”。
数据范围
1≤n≤1001≤n≤100
输入样例:
2
3
.##
..#
#..
0 0 2 2
5
.....
###.#
..#..
###..
...#.
0 0 4 0
输出样例:
YES
NO
完整代码:
#include<bits/stdc++.h>//头文件,这个很好用
using namespace std;
int n,x1,x2,ya1,ya2,vis[105][105];
char mg;//用来放输入变量的
bool flag;//用来记录是否有解
int dx[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//放方向数组的,虽然说数组都是从0开始的,但是开辟的数组空间还是要够才得行
//现在开始写DFS模板
void dfs(int x,int y)
{
for (int i=0;i<4;i++)//遍历新点的所有相邻点
{
int nx=x+dx[i][0];
int ny=y+dx[i][1];
if(nx>=0&&nx<n&&ny>=0&&ny<n&&vis[nx][ny]==0)//检查新点的每个相邻点是否符合遍历要求
{
vis[nx][ny]=1;//将符合要求的相邻点标记为旧点
if(nx==x2&&ny==ya2)
{
printf("YES\n");
flag=true;
break;
}
else
dfs(nx,ny);
}
}
}
//
1.注意在写DFS时候,常用模板:返回值为void,传入起点,遍历起点的所有相邻点(不必担心这个起点和终点重合的情况,后面有一个检查的机制在main 函数里面),
2.遍历的时候利用一个for循环+一个方向数组,对于每一个相邻的点都要进行边界检查+新旧检查
3.将此点标记为旧点;
4.判断是否为终点:是->return 不是->继续搜他的相邻点
int main()
{
int N;
scanf("%d",&N);
while(N--)//很好解决了检查多组数据
{
memset(vis,0,sizeof(vis));
flag=false;//清零功能
scanf("%d",&n);
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
{
cin>>mg;
if(mg=='#')
vis[i][j]=1;
}//实际上节省了一般DFS需要的map空间(看具体的题目)
scanf("%d %d",&x1,&ya1);
scanf("%d %d",&x2,&ya2);
if (vis[x1][ya1]||vis[x2][ya2])//检车起点与终点重合的情况
{
printf("NO\n");
continue;//当起止点重合时,跳出if-else循环
}
else
dfs(x1,ya1);
if(!flag)//还有一个flag检查机制
printf("NO\n");
}
return 0;
}
Tip:
hhh,前几天确实偷懒了,后面补上;