搜索算法(迷宫问题)

搜索算法

盼来盼去终于又要开始学习算法了!
笔者自学算法,所以学习顺序以个人舒服的形式!

一,DFS(深搜)

用例子来看:
问题:
有一个迷宫,以1 2形式来表示————1表示是空地,即可以行走,2表示是障碍物,即无法通行。该迷宫由一个矩阵形式表示。

1  1  2  1
1  1  1  1
1  1  2  1
1  2  1  1
1  1  1  2
有终点和起点,我们需要计算从起点到达终点的最短路径!
在这里插入图片描述
准备代码为

int q,p,step;//(p,q)为终点坐标 
int mmin=999999;
int a[100][100];//1表示空地//2表示障碍物 
int v[100][100];//1表示访问//0表示未访问 

解析代码为(优先理解该代码,方便后面理解)

void dfs(int x,int y,int step)
{
	if(x==p&&y==q)
	{
		if(step<mmin)
			mmin=step;
		return;
	}
	//顺时针试探
	//→
	if(a[x][y+1]==1&&v[x][y+1]==0)
	{
		v[x][y+1]=1;
		dfs(x,y+1,step+1);
		v[x][y+1]=0;
	}
	//↓
	if(a[x+1][y]==1&&v[x+1][y]==0)
	{
		v[x+1][y]=1;
		dfs(x+1,y,step+1);
		v[x+1][y]=0;
	}
	//←
	if(a[x][y-1]==1&&v[x][y-1]==0)
	{
		v[x][y-1]=1;
		dfs(x,y-1,step+1);
		v[x][y-1]=0;
	}
	//↑
	if(a[x-1][y]==1&&v[x-1][y]==0)
	{
		v[x-1][y]=1;
		dfs(x-1,y,step+1);
		v[x-1][y]=0;
	}
	return;
}

优化代码为

int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
void dfs(int x,int y,int step)
{
	if(x==p&&y==q)
	{
		if(step<mmin)
			mmin=step;
		return;
	}
	//顺时针试探
	for(int k=0;k<=3;k++)
	{
		int tx,ty;
		tx=x+dx[k];
		ty=y+dy[k];
		if(a[tx][ty]==1&&v[tx][ty]==0)
		{
			v[tx][ty]=1;
			dfs(tx,ty,step+1);
			v[tx][ty]=0;
		}
	}
	return;
}

int main()

int main(int argc,char*argv[])
{
	int m,n;
	cin>>m>>n;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>a[i][j];
		}
	}
	int qi,z;
	cin>>qi>>z>>p>>q;
	v[qi][z]=1;
	dfs(qi,z,0);
	cout<<mmin;
	return 0; 
} 

测试数据:
5 4
1 1 2 1
1 1 1 1
1 1 2 1
1 2 1 1
1 1 1 2
1 1 4 3
结果为7

二,BDF (广搜)

理解:

之所以称之为宽度优先算法,是因为算法自始至终一直通过已找到和未找到顶点之间的边界向外扩展,就是说,算法首先搜索和s距离为k的所有顶点,然后再去搜索和S距离为k+l的其他顶点。
——取自百度百科

  在笔者看来,任何知识的运用首先应该是从定义理解出发,只有明白了最基本的意义才能够熟悉并且巧妙的运用,因此在介绍bfs时,我想先从定义上入手,再去解决问题。

  根据上文引用:“首先搜索和s距离为k的所有顶点,然后再去搜索和S距离为k+l的其他顶点”对此我们可以知道bfs与dfs不同的是bfs在行动时就已经开始在寻找不同路径,而dfs是只要找到了一条可通过则进行下一步步骤(因此dfs后面会出现回溯这一步)
  可以举一个形象的例子,学校里举办寻宝活动,大家组队,因为学校特别大且道路特别多,所以找到宝藏点需要去探索。小A决定团体活动,大家一起行动,如果发现路不对,则一起再寻找其它路;而小B决定分开行动,大家走不同的路,总有一个人是正确的道路。显而易见从概率的角度分析,小B队伍获胜的概率远远大于小A;这里也可以相类似与dfs(小A)和bfs(小B).
  解释结束,我们还是以迷宫问题为代表。
在这里插入图片描述
这里用到了queue。根据bfs定义可以很明显知道这里用queue比较适合

int a[100][100];
int v[100][100];

struct point {
	int x;
	int y;
	int step;
};

queue<point> r;//申请队列
int dx[4] = { 0,1,0,-1 };
int dy[4] = { 1,0,-1,0 };

int main(int argc, char* argv[])
{
	int n, m;
	int st, end, p, q;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			cin >> a[i][j];
	cin >> st >> end >> p >> q;
	
	//bfs
	point start;
	start.x = st;
	start.y = end;
	start.step = 0;
	r.push(start);//将起点入队
	v[st][end] = 1;
	int flag = 0;
	while (!r.empty())
	{
		int x = r.front().x, y = r.front().y;
		if (x == p && y == q)
		{
			flag = 1;
			cout << r.front().step;
			break;
		}
		for (int k = 0; k <= 3; k++)
		{
			int tx, ty;
			tx = x + dx[k];
			ty = y + dy[k];
			if (a[tx][ty] == 1 && v[tx][ty] == 0)
			{
				point temp;
				temp.x = tx;
				temp.y = ty;
				temp.step = r.front().step + 1;
				r.push(temp);
				v[tx][ty] = 1;
			}
		}
		r.pop();//拓展完了需要将对首元素出队
	}
	if (flag == 0)
	{
		cout << "no ans";
	}
	return 0;
}
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
回答: 广度优先算法可以用来解决迷宫问题。在迷宫问题中,我们可以使用一个二维数组来表示迷宫的状态,其中墙的位置用1表示,可以走的位置用0表示。通过设置一个vis\[\]数组来记录每个顶点是否被访问过,vis\[i\]为0表示未被访问,vis\[i\]为1表示已被访问。通过广度优先搜索算法,我们可以找到从出口到入口的路径。具体步骤是将起点加入队列,然后不断从队列中取出顶点,并将其周围未访问过的顶点加入队列,直到找到出口。同时,我们可以使用一个pre指针来指向每个顶点的前一个顶点,以便最后找出完整的路径。\[1\] 引用\[2\]中提到了如何用一个二维数组初始化迷宫,并归定不同的迷宫数组状态。例如,maze\[i\]\[j\]=0表示可以走,maze\[i\]\[j\]=1表示墙,maze\[i\]\[j\]=2表示无法继续走,maze\[i\]\[j\]=3表示已经走过的路径。 需要注意的是,迷宫问题可能会遇到时间限制,因此在实际应用中需要考虑算法的效率和优化。\[3\] #### 引用[.reference_title] - *1* [利用广度优先搜索(bfs)来解决迷宫问题](https://blog.csdn.net/weixin_45843077/article/details/104383595)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [利用广度优先和深度优先算法解决迷宫问题算法设计与分析】图搜索问题>](https://blog.csdn.net/weixin_50400808/article/details/122571191)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [广度优先搜索(BFS)——迷宫问题(POJ 4127)](https://blog.csdn.net/weixin_44572229/article/details/119679593)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值