绘制一个n*m的迷宫,例如:
3x3的迷宫,迷宫为:
1 1 1
1 2 3
1 1 1
假设1为可通行,其他均为不可,可上下左右四个方向行走,默认(0,0)为起点,设置(2,2)为终点
那么dfs走迷宫的方式就为:
可能这个憨憨图画的不是很好,简单来说dfs就是试探四个方向,能走就走,不能走就回溯,一直走到能到终点为止,并且能找到所有能到终点的路径
方向为上下左右:
由于可以找所有人路径,所以我们设置一个值来存放最小的步数就可以啦,理论好理解,主要是代码:
#include "stdio.h"
#include "iostream"
using namespace std;
typedef long long ll;
ll n, m; //n*m的迷宫
ll end_x, end_y;
ll start_x, start_y;
ll the_min = 9999999;
ll the_map[100][100];//1为可行
ll v[100][100]; //相当于草稿纸,拿来画出当前的(x,y)的标记,没走过为0,走过为1
void dfs(ll x, ll y, ll step)
{
if (x == end_x && y == end_y){ //首先判断停止条件
if (step < the_min)
the_min = step;
return ; //这一条路走到终点了,回溯
}
if (v[x][y + 1] != 1&&the_map[x][y+1]==1){//向下试探,(x,y)是图中的没走过点
v[x][y + 1] = 1; //走进(x,y+1)这个点,并将其标记为走过
dfs(x, y + 1, step + 1);//进入(x,y+1)该走的路,进了一趟鬼门关
v[x][y + 1] = 0;//(x,y+1)重生啦,他已经从上面的dfs走到终点过了,现在重生了可以试其他路了
}
if(v[x+1][y]!=1&&the_map[x+1][y]==1){//向右试探
v[x+1][y] = 1;
dfs(x+1, y, step + 1);
v[x+1][y] = 0;
}
if(v[x-1][y]!=1&&the_map[x-1][y]==1){//向左
v[x-1][y] = 1;
dfs(x-1, y, step + 1);
v[x-1][y] = 0;
}
if(v[x][y-1]!=1&&the_map[x][y-1]==1){//向上
v[x][y-1] = 1;
dfs(x, y-1, step + 1);
v[x][y-1] = 0;
}
}
int main()
{
cin>>n>>m;//设置迷宫大小
for (ll i = 0; i < n; i++){
for (ll j = 0; j < m; j++){
cin>>the_map[i][j];//绘制迷宫
}
}
cin>>end_x>>end_y;//输入终点的坐标
v[0][0]=1;//将起点设为走过,因为我们当前就在起点
dfs(0,0,0);//默认(0,0)为起点,当前步数为0
cout<<the_min<<endl;
return 0;
}
当然这样写的话,如果有很多方向怎么办,难道还是要一个一个if来判断吗?
于是我们可以用数组来表示走的方向,然后用循环来实现试探路径。
int dir[5][2] = { {-1,0},{1,0},{0,-1},{0,1} };
void dfs(ll x, ll y, ll step) {//写出返回值类型,传入参数是什么
if (x==end_x&&y==end_y) {//退出条件
the_min = min(step, the_min);
return ;
}
for (int i = 0; i < 4; i++) {//循环四个方向
int new_x = x + dir[i][0];
int new_y = y + dir[i][1];
if (the_map[new_x][new_y] == 1 && vis[new_x][new_y] == 0) {
vis[new_x][new_y] = 1;
dfs(new_x, new_y, step + 1);
vis[new_x][new_y] = 0;
}
}
}