利用深度优先搜索(dfs)来解决迷宫问题

利用深度优先搜索(dfs)来解决迷宫问题

一.深度优先搜索(dfs)

1.什么叫dfs

深度优先搜索类似于树的先序遍历
是利用栈或者递归的方式实现的,体现出了后进先出的特点;
通俗来说就是一次访问一条路,一直朝着一个方向探索,直到遇到死路退回到前一个分支,继续探索;
一般来说,深度搜索解决的问题主要为寻求所有解和连通性

2.遍历过程

(1)从图中某个初始顶点v出发,首先访问初始顶点v。
(2)然后依次从v的未被访问的邻接点w,再从w出发进行深度优先遍历,直到图中所有与v有路径相通的的顶点都被访问过为止。

3.算法设计

解决问题:
(1)如何确定一个顶点是否访问过?
设置一个visited[]全局数组,
visited[i]=0表示顶点i没有访问;
visited[i]=1表示顶点i已经访问过。
(在图中也可以修改图本身来实现)

4.dfs算法模板

void dfs(int s)
{
	if(找到解了)
	{
		相应的操作;
		return}
	尝试每一种可能
	{
		if(满足条件)
		{
			标记走过;
			进行下一步dfs;
			回溯一步;	//恢复原状态
		}
	}
}

二.例题示范

棋盘问题

(1)问题描述:

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
(2)输入:

输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
(3)输出:

对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
(4)样例输入:

2 1
#.
.#
4 4
…#
…#.
.#…
#…
-1 -1

(5)样例输出

2
1

#include<stdio.h>
#include<string.h>
int n,k;
char map[10][10];
int sum;
int visited[10];
void dfs(int y,int t)
{
	if(t==k)
	{
		sum++;
		return ;
	}
		//满足条件,次数加1,返回;
	if(y<=n)
	dfs(y+1,t);
		//一直调用到最后一行,从最后一行开始,
		//考虑到每一种情况;
	for(int i=1;i<=n;i++)
	{
		if(map[y][i]=='#'&&visited[i]==0)
		{	//需要满足的条件
			visited[i]=1;
				//标记已经走过
			dfs(y+1,t+1);
				//继续下一步dfs
			visited[i]=0;
				//恢复初始状态
		}
	}
}
int main()
{
	while(1)
	{
		sum=0;
		scanf("%d%d",&n,&k);
		if(n==-1&&k==-1)
			break;
			memset(map,0,sizeof(map));
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
			scanf(" %c",&map[i][j]);
		dfs(1,0);
			//初始化y为第一行,次数为0
		printf("%d\n",sum);
	}
	return 0;
}

三.代码

	//用dfs来计算最短路径
#include<stdio.h>
int r,c,num=10000;
char map[41][41];
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
void dfs(int x,int y,int k)
{
	if(x==r&&y==c)
	{
		if(num>k)
		{
			num=k;
		}
	}
	for(int i=0;i<4;i++)
	{
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=1&&nx<=c&&ny>=1&&ny<=r&&map[ny][nx]=='.')
		{
			map[ny][nx]='#';
			dfs(nx,ny,k+1);
			map[ny][nx]='.';
		}
	}
}
int main()
{
	scanf("%d%d",&r,&c);
	for(int i=1;i<=r;i++)
	{
		for(int j=1;j<=c;j++)
		{
			scanf(" %c",&map[i][j]);
		}
	}
	map[1][1]='#';
	dfs(1,1,1);
	printf("%d",num);
}
//dfs遍历是否能够从(ha,la)到(hb,lb)
#include<stdio.h>
#include<string.h>
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
int n,ha,la,hb,lb,nx,ny;
bool flag;
char map[200][200];
void dfs(int x,int y)
{
	for(int i=0;i<4;i++)
	{
		nx=x+dx[i];
		ny=y+dy[i];
		if(nx>=0&&nx<n&&ny>=0&&ny<n&&map[nx][ny]=='.')
		{
			map[nx][ny]='#';
			if(nx==hb&&ny==lb)
			{
				printf("YES\n");
				flag=true;
				break;
			}
			else
				dfs(nx,ny);
		}
	}
}
int main()
{
	int k;
	scanf("%d",&k);
	for(int i=0;i<k;i++)
	{
		flag=false;
		scanf("%d",&n);
		memset(map,'#',sizeof(map));
		for(int j=0;j<n;j++)
			for(int h=0;h<n;h++)
			{
				scanf(" %c",&map[j][h]);
			}
		scanf("%d%d%d%d",&ha,&la,&hb,&lb);
		if(map[ha][la]=='#'||map[hb][lb]=='#')
		{
			printf("NO\n");
			continue; 
		}
		else
		{
			map[ha][la]='#';
			//标记起点走过
			dfs(ha,la);
		}
		if(!flag)
		printf("NO\n");
	}
	return 0;
}
//棋盘问题代码
#include<stdio.h>
#include<string.h>
int n,k;
char map[10][10];
int sum;
int visited[10];
void dfs(int y,int t)
{
	if(t==k)
	{
		sum++;
		return ;
	}
	if(y<=n)
	dfs(y+1,t);
	for(int i=1;i<=n;i++)
	{
		if(map[y][i]=='#'&&visited[i]==0)
		{
			visited[i]=1;
			dfs(y+1,t+1);
			visited[i]=0;
		}
	}
}
int main()
{
	while(1)
	{
		sum=0;
		scanf("%d%d",&n,&k);
		if(n==-1&&k==-1)
			break;
			memset(map,0,sizeof(map));
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
			scanf(" %c",&map[i][j]);
		dfs(1,0);
		printf("%d\n",sum);
	}
	return 0;
}
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我来为您讲解如何使用DFS算法来解决迷宫问题DFS算法是一种搜索算法,它通过深度优先遍历图或树来寻找目标节点。在迷宫问题中,我们可以将每一个可行的位置看做是图中的一个节点,然后使用DFS算法来搜索从起点到终点的路径。 具体的实现步骤如下: 1. 定义一个二维数组来表示迷宫,其中0表示可以通过的通道,1表示障碍物。 2. 定义一个visited数组来记录每个节点是否被访问过。 3. 定义一个栈来保存搜索过程中经过的节点。 4. 从起点开始,将其加入栈中,并标记为已经访问。 5. 对于栈中的每个节点,依次遍历其相邻节点,如果相邻节点未被访问过且可以通过,则将其加入栈中,并标记为已经访问。 6. 如果最终找到了终点,搜索结束,返回路径;否则,回溯到上一个节点,继续搜索直到找到终点或者栈为空。 7. 如果栈为空,表示没有找到从起点到终点的路径。 下面是一个简单的实现示例代码: ```python def dfs(maze, visited, path, start, end): if start == end: return path + [end] visited[start[0]][start[1]] = True for dx, dy in [(1, 0), (-1, 0), (0, 1), (0, -1)]: x, y = start[0] + dx, start[1] + dy if 0 <= x < len(maze) and 0 <= y < len(maze[0]) and not visited[x][y] and maze[x][y] == 0: res = dfs(maze, visited, path + [start], (x, y), end) if res: return res return None # 测试代码 maze = [[0, 1, 0, 0, 0], [0, 1, 0, 1, 0], [0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 1, 0]] visited = [[False] * len(maze[0]) for _ in range(len(maze))] path = [] start = (0, 0) end = (4, 4) res = dfs(maze, visited, path, start, end) if res: print(res) else: print("找不到路径!") ``` 希望这个回答可以帮助您解决迷宫问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值