迷宫问题(dfs)

该博客探讨了如何使用深度优先搜索(DFS)算法解决迷宫问题。内容包括输入迷宫的规格,以及如何通过DFS找到从起点到终点的路径。案例展示了一个具体的输入输出示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:
给一个 n 行 m 列的 2 维的迷宫,'S'表示迷宫额起点,'T'表示迷宫的终点,'#'表示不能通过的点,'.' 表示可以通过的点。你需要从'S'出发走到'T',每次只能上下左右走动,并且只能进入能通过的点,每个点只能通过一次。现在要求你求出有多少种通过迷宫的的方案。

輸入:

第一行输入 nnm(1n,m10) 表示迷宫大小

接下来输入 nn 行字符串表示迷宫

输出:通过迷宫的方法

输入:

2 3
S.#
..T
输出: 2

输入:

3 3
S..
.#.
..T

输出:2

import java.util.*;
//import java.io.*; 
public class Main {
	 static int ans,n,m;
	 static String mat[]=new String[11];
	 static int dir[][]= {{1,0},{0,1},{-1,0},{0,-1}};//对应的上下左右4各方向  
	 static boolean [][]visited=new boolean[11][11];
	 
	 static void dfs(int x,int y)
	 {
		 visited[x][y]=true;
		 if(mat[x].charAt(y)=='T') {
			 ans++;
		    return ;
		 }
		 if(mat[x].charAt(y)=='#')
		 {
			 return ;
		 }
		 for(int i=0;i<dir.length;i++)
		 {
			 x=x+dir[i][0];
			 y=y+dir[i][1];
			 if((-1<x&&x<n)&&(-1<y&&y<m))
			 {
				 if(visited[x][y]==false)
				 {
					 visited[x][y]=true;
					 dfs(x,y);
					 visited[x][y]=false;//hui shuo
				
			 }
		 }
			 x=x-dir[i][0];//hui shuo
			 y=y-dir[i][1];
		 }
		 
		 
	 }
   public static void main(String args[])
   {
	   //BufferedReader sc = new BufferedReader (new InputStreamReader(System.in));  
	   Scanner sc=new Scanner(System.in);
	 //  int n=0,m=0;
	 n=sc.nextInt();
	 m=sc.nextInt();
	   for(int i=0;i<n;i++)
	   {
		   mat[i]=sc.next();//每一行当作字符串读入
	   }
	   int x=0,y=0;
	   for(int i=0;i<n;i++)
	   {
		   for(int j=0;j<m;j++)
		   {
			   if(mat[i].charAt(j)=='S')
			   { x=i;
			       y=j;
			   }
		   }
	   }
	    ans=0;
	   dfs(x,y);
	   System.out.println(ans);
	   
	   
   }
}
#include <stdio.h>
#include <stdlib.h>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int ans =0;
int b [100][100];
 char a [1000][1000];
int main(int argc, char *argv[])
 
 { 
 int  x1,y1,x2,y2;
 int n,m,i,j;
 scanf("%d%d",&n,&m);

 for(i=0;i<n;i++)
 {
	 	scanf("%s",a[i]);
 }
 for(i=0;i<n;i++)
 {
	 	for(j=0;j<m;j++)
	 	{
	 		if(a[i][j]=='S')
	 		{
	 			x1 = i; y1= j;
	 			
	 		}else if(a[i][j]=='T')
	 		{
	 			x2= i;
	 			y2= j;
	 		}
	 	}
 }
	b[x1][y1]=1;
	dfs(x1,y1,x2,y2,n,m);
	printf("%d",ans);
	return 0;
}
void dfs (int x1 ,int y1,int x2,int y2,int n,int m)
{
	int i;
	int tx ,ty;
	if(x1==x2&&y2==y1)
	{
		ans++;
		return ;
	}
	 int xx[4] ={0,1,-1,0};
	 int yy[4]= {1,0,0,-1};
	 for(i=0;i<4;i++)
	 {
	 	tx = x1+xx[i];
	 	ty = y1+yy[i];
	 	if(a[tx][ty]!='#'&&tx>=0&&tx<n&&ty>=0&&ty<m&&b[tx][ty]!=1)
	 	{
	 		b[tx][ty]=1;
	 		dfs(tx,ty,x2,y2,n,m);
	 		b[tx][ty]=0;
	 	}
	 }
	
	
}



### 迷宫问题中的DFS和BFS算法 #### DFS(深度优先搜索) 在迷宫求解中,DFS采用的是深入探索的方式直到无法继续前进为止再回溯其他可能路径的方法。该方法利用栈结构来记录访问过的节以及当前所处位置,在遇到死胡同时会返回上一步并尝试新的方向[^1]。 对于迷宫问题而言,当仅需找到一条从起到终的有效路径而不在乎是否为最短路径时,DFS是一个不错的选择;然而其缺在于可能会遍历较多不必要的分支从而浪费时间资源[^2]。 ```cpp void dfs(int x, int y){ if (maze[x][y] == END){ // 到达出口 success = true; return ; } visited[x][y] = true; // 标记已走过 for (int i=0;i<4;++i){ // 尝试四个方向移动 int nx=x+dx[i], ny=y+dy[i]; if (!success && isValid(nx,ny)){ path.push_back({nx,ny}); dfs(nx,ny); if(!success) path.pop_back(); // 回溯 } } } ``` #### BFS(广度优先搜索) 相比之下,BFS则更倾向于一层层向外扩展邻居结直至触及目标位停止。此过程借助队列完成,每次都将新发现却未曾踏足之处加入待处理列表之中等待后续考察。由于这种特性决定了它总能最先抵达离起始最近的目的地因此特别适合用来寻找两间最短距离的问题场景下使用[^3]。 ```cpp bool bfs(){ queue<pair<int,int>> q; vector<vector<bool>> seen(rows,vector<bool>(cols,false)); q.emplace(startX,startY); seen[startX][startY]=true; while(!q.empty()){ auto [cx,cy]=q.front(); q.pop(); if(maze[cx][cy]==END) return true; for(auto& d : directions){ int nx=cx+d.first , ny=cy+d.second ; if(isValid(nx,ny)&&!seen[nx][ny]){ parent[{nx,ny}]={cx,cy}; seen[nx][ny]=true; q.emplace(nx,ny); } } } return false; } ``` #### 应用对比 - **适用范围** - 如果只需要知道是否存在通路而不关心具体长度,则可以考虑效率较高的DFS。 - 若要获取确切的最短路线方案,则应选用能够保证首次到达即最优解特性的BFS。 - **性能考量** - 对于较小规模的地图数据集来说两者差异不大; - 随着地图尺寸增大,考虑到内存占用等因素影响,通常认为BFS所需额外存储空间较大因为它要保存每一层所有未被探测过的位置信息以便下一步操作,所以实际运行速度未必优于DFS。 - **实现难度** - 实现方面二者都较为简单直观易于理解掌握,但在编码细节上有一定差别比如循环终止条件判断、边界情况处理等都需要仔细斟酌确保逻辑严谨无误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值