走迷宫
题目描述:
给定一个N×M 的网格迷宫 G。G 的每个格子要么是道路,要么是障碍物(道路用 1 表示,障碍物用 00表示)。
已知迷宫的入口位置为 (x1,y1),出口位置为 (x2,y2)。问从入口走到出口,最少要走多少个格子。
输入描述:
输入第 11 行包含两个正整数 N,M,分别表示迷宫的大小。
接下来输入一个 MN×M 的矩阵。若 Gi,j=1 表示其为道路,否则表示其为障碍物。
最后一行输入四个整数 x1,y1,x2,y2,表示入口的位置和出口的位置。
输出描述:
输出仅一行,包含一个整数表示答案。
若无法从入口到出口,则输出 -1。
输入样例:
5 5
1 0 1 1 0
1 1 0 1 1
0 1 0 1 1
1 1 1 1 1
1 0 0 0 1
1 1 5 5
输出样例:
8
DFS代码(复杂度较高)
//dfs()
#include <iostream>
#define INF 99999999
int a[101][101],vis[101][101]={0};//a储存地图 vis标记走没走过
int n,m,startx,starty,endx,endy,minCount=INF;
int nextSpot[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//方向数组
void dfs(int x,int y,int count) {//维护横纵坐标和当前步数
if (count>=minCount) return;//当前步数大于到终点的最小步数就直接结束
if (x==endx&&y==endy) {//到达终点
minCount=minCount<count?minCount:count;//更新最小步数
return;
}
for (int i=0;i<4;i++) {//循环方向数组
int nextx=x+nextSpot[i][0];//计算下一步的坐标
int nexty=y+nextSpot[i][1];
if (nextx<=0||nexty<=0||nextx>n||nexty>m) continue;//坐标越界直接结束本循环
if (a[nextx][nexty]==1&&vis[nextx][nexty]==0) {//如果该坐标的值是 1(可走)并且没走过
vis[nextx][nexty]=1;//标记走过
dfs(nextx,nexty,count+1);//深搜下一步,步数加一
vis[nextx][nexty]=0;//深搜完取消标记
}
}
}
int main() {
cin>>n>>m;
for (int i=1;i<=n;i++) {
for (int j=1;j<=m;j++) {
cin>>a[i][j];
}
}
cin>>startx>>starty>>endx>>endy;
dfs(startx,starty,0);//刚开始步数为零
if (minCount==INF) cout<<-1;//没路
else cout<<minCount;
return 0;
}
BFS代码(可以AC)
//bfs()
#include <iostream>
#include <queue>
using namespace std;
struct place {
int x;//横坐标
int y;//纵坐标
int count;//到达该节点走过的最小步数
};
int main() {
int a[101][101],vis[101][101]={0};//a储存地图 vis标记走没走过
int nextSpot[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//方向数组
int n,m,startx,starty,endx,endy;
cin>>n>>m;
for (int i=1;i<=n;i++) {
for (int j=1;j<=m;j++) {
cin>>a[i][j];
}
}
cin>>startx>>starty>>endx>>endy;
queue<struct place> que;//定义队列
struct place temp;
temp.x=startx;
temp.y=starty;
temp.count=0;
que.push(temp);//将初始坐标放入队列
while (!que.empty()) {//队列为空,停止扩展
struct place nextPlace,front=que.front();//nextPlace:下一坐标,front:当前栈顶元素
for (int i=0;i<4;i++) {//循环方向数组
nextPlace.x=front.x+nextSpot[i][0];//计算下一步的坐标
nextPlace.y=front.y+nextSpot[i][1];
nextPlace.count=front.count+1;
if (nextPlace.x<=0||nextPlace.y<=0||nextPlace.x>n||nextPlace.y>m) continue;//坐标越界直接结束本循环
if (vis[nextPlace.x][nextPlace.y]==1||a[nextPlace.x][nextPlace.y]==0) continue;//如果该坐标的值是 0(不可走)或者走过就结束本次循环
if (nextPlace.x==endx&&nextPlace.y==endy) {//走到终点
cout<<nextPlace.count;
return 0;//因为深搜特性,第一次找到的是最优解,直接结束程序即可
}
que.push(nextPlace);//不是终点就加入队列,等待下一次被扩展
vis[nextPlace.x][nextPlace.y]=1;//标记本坐标已经被扩展
}
que.pop();//队头被扩展完,则出队
}
cout<<-1;//没找到终点
return 0;
}