dfs初入门必刷题,一篇文章让你学会dfs(迷宫)

首先我们先假设有一个4*6的迷宫,左上角为起点,右下角为终点。
"0”是通道,"1"是障碍物
而我们的目标则是寻找从起点到终点的最短路径
0,1,0,0,0,0,
0,0,0,1,0,0,
0,0,1,0,0,1,
1,1,0,0,0,0,

接着,我们把左上角作为坐标原点,建立坐标轴,向下为x轴,向右为y轴,然后我们在迷宫周围补一圈"0",让起点坐标为(1,1),最后把它存到数组中。

0,0,0,0,0,0,0,    
0,0,1,0,0,0,0,
0,0,0,0,1,0,0,
0,0,0,1,0,0,1,
0,1,1,0,0,0,0,

那么我们应该怎么样才可以用代码表示位置的移动呢?
其实很简单,本质上,我们从起点向下移动一格,其实就是由坐标(1,1)变成(2,1)的过程,即(x+1,y+0)
那么向其他方向移动,也是同理

const int dirx[5] = {1, 0, -1, 0};
const int diry[5] = {0, 1, 0, -1};
const char dir[5] = {'D','R','U','L'};
// 我们定义到达的坐标为 tox,toy
// tox = x + dirx[i],toy = y + diry[i]

然后,我们还需要一个数组标记之前的路径,并且建立一个函数防止我们出现走出边界走回头路,以及撞墙的情况。

const int row =4,col =6;
const int maxrc=6;
int maze[row+1][col+1]=
{
0,0,0,0,0,0,0,    
0,0,1,0,0,0,0,
0,0,0,0,1,0,0,
0,0,0,1,0,0,1,
0,1,1,0,0,0,0,
};
int mins[maxrc+5][maxrc+5];  //标记每个位置的最小步数
int best = 1<<28;  //最佳路径 
char a[row*col+5]; //记录路径的方向 
string stem;//最短的路径记录 
bool judge(int x,int y){
	if(x >= 1 && x <= row && y >= 1 && y <= col && maze[x][y] != 1)
		return true;
	return false;
} 

到这里,dfs的全部准备活动就结束了。
我们进入正题

dfs又叫作深度优先搜索,在迷宫中就是要遍历所有可能的下个位置的坐标,再由下个坐标一直向深遍历搜索

for(int i =0;i < 4;i++){
		int tox = x + dirx[i];
		int toy = y + diry[i];
		if(judge(tox,toy) && pos+1<=mins[tox][toy]) 	
		//保证不会出现回头路等情况,同时保证步数不会大于之前储存的最小步数。
		{
			maze[tox][toy] = 1;    //标记当前位置已经走过
			mins[tox][toy] = pos+1;		//储存步数
			a[pos] = dir[i];	//储存该pos的走的方向
			dfs(tox,toy,pos+1);
			maze[tox][toy] =0;	//即将进入下层循环,回到该位置未走过的状态,取消标记
		}
	}

如果到达终点,则返回并存储数据。

if(x == row && y ==col ){
		string s;
		for(int i = 0; i < pos; i++ )
			s += a[i];	//记录完整路径
		if(pos < best){ 	//如果新路径小于上次记录的最佳路径,则更新
			best = pos;
			stem = s;
		}
		else if(pos == best && stem > s)
			stem =s;
		return ;
	}

那么完整的dfs就是这样:

void dfs(int x,int y,int pos){
	if(pos > best)		//剪枝,减去没必要的操作
		return ;
	if(x == row && y ==col ){
		string s;
		for(int i = 0; i < pos; i++ )
			s += a[i];
		if(pos < best){
			best = pos;
			stem = s;
		}
		else if(pos == best && stem > s)
			stem =s;
		return ;
	}
	for(int i =0;i < 4;i++){
		int tox = x + dirx[i];
		int toy = y + diry[i];
		if(judge(tox,toy) && pos+1<=mins[tox][toy])
		{
			maze[tox][toy] = 1;
			mins[tox][toy] = pos+1;
			a[pos] = dir[i];
			dfs(tox,toy,pos+1);
			maze[tox][toy] =0;
		}
	}
}

最后完整代码奉上

#include<iostream>
#include<cstring>
using namespace std;

const int dirx[5] = {1, 0, -1, 0};
const int diry[5] = {0, 1, 0, -1};
const char dir[5] = {'D','R','U','L'};
//向下x,向右y 
const int row =4,col =6;
const int maxrc=6;

int maze[row+1][col+1]=
{
0,0,0,0,0,0,0,    
0,0,1,0,0,0,0,
0,0,0,0,1,0,0,
0,0,0,1,0,0,1,
0,1,1,0,0,0,0,
};

int mins[maxrc+5][maxrc+5];
int best = 1<<28;  //最佳路径 
char a[row*col+5]; //记录路径的方向 
string stem;//最短的路径记录 
bool judge(int x,int y){
	if(x >= 1 && x <= row && y >= 1 && y <= col && maze[x][y] != 1)
		return true;
	return false;
} 

void dfs(int x,int y,int pos){
	if(pos > best)
		return ;
	if(x == row && y ==col ){
		string s;
		for(int i = 0; i < pos; i++ )
			s += a[i];
		if(pos < best){
			best = pos;
			stem = s;
		}
		else if(pos == best && stem > s)
			stem =s;
		return ;
	}
	for(int i =0;i < 4;i++){
		int tox = x + dirx[i];
		int toy = y + diry[i];
		if(judge(tox,toy) && pos+1<=mins[tox][toy])
		{
			maze[tox][toy] = 1;
			mins[tox][toy] = pos+1;
			a[pos] = dir[i];
			dfs(tox,toy,pos+1);
			maze[tox][toy] =0;
		}
	}
}
int main(){

	memset(mins,1,sizeof(mins));
	maze[1][1]=1;
	dfs(1,1,1);
	cout<<stem<<endl;
	cout<<best-1<<endl;
	return 0;
}
 
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值