蓝桥杯——迷宫(BFS)

文章介绍了迷宫问题本质上是一个寻找最短路径的问题,推荐使用BFS结合堆来解决,而非DFS,因为BFS避免了回溯,时间复杂度更低。BFS通过每轮遍历更新节点的最短距离,确保每次处理的节点距离最小。提供的代码示例展示了如何利用BFS和优先队列实现这一算法,寻找从起点到终点的最短路径和最少步数。

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

  • 思路
    迷宫问题本质是一个最短路径问题。对于最短路径问题一般使用bfs+堆(先广搜索)而不会用dfs。因为dfs需要反复回溯,时间复杂度很高,而bfs每个节点只需要遍历一次,时间复杂度为O(n)(不算堆排序)。
  • bfs求最短路劲的原理
    bfs求最短路径的思路是每轮遍历都求出当前节点到起点的最短距离,如果发现节点的最短距离已经求过那么就不用再遍历这个节点。由于再bfs+堆中每个节点第一次被遍历到时它的权重就是起点到该节点的最短距离,所以实际上对于一张图每个节点只需遍历一次。bfs+堆能保证每个遍历到的节点的距离都是最小是基于以下这个事实:
    起点到节点 i 的最短距离 = m i n ( 起点到 i 的邻接点最短距离 ) + 1 起点到节点i的最短距离=min(起点到i的邻接点最短距离)+1 起点到节点i的最短距离=min(起点到i的邻接点最短距离)+1
  • 迷宫问题模板
  1. 题目
  2. 核心代码
//核心代码
void bfs(){
	//广度优先遍历
	priority_queue<Node,vector<Node>,Comp> minHeap;
	//放入第一个节点
	Node first=Node();
	first.path="";
	//表示当前点到起点的最短距离
	first.sum=0;
	first.x=first.y=1;
	minHeap.emplace(first);
	visited[1][1]=0;
	int x,y;
	int num=0;
	while(!minHeap.empty()){
		//非空不断的迭代
		Node head=minHeap.top();
		minHeap.pop();
		x=head.x;
		y=head.y;
		//先检查一下大小
		if(x==X&&y==Y){
			//到达出口 
			bestNum=head.sum;
			bestStr=head.path;
			num=1;
			return;
		} 
		if(head.sum>=bestNum)	break; 
		//上下左右
		for(int i=0;i<=3;i++){
			if(check(x+d[i][0],y+d[i][1])){
				
				//当前路径不是最短距离直接跳过 
				if((head.sum+1)>visited[x+d[i][0]][y+d[i][1]]) 	continue;
				//创建新节点
				Node newNode=Node();
				newNode.x=x+d[i][0];
				newNode.y=y+d[i][1];
				newNode.sum=head.sum+1;
				visited[newNode.x][newNode.y]=head.sum+1; 
				newNode.path=head.path+step[i];
				//插入堆中
				minHeap.emplace(newNode); 
			}
		}
	}
}
  1. 模板
#include <iostream>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
#include <bits/stdc++.h>
#include <fstream>
#include <vector>
#include <queue>
int X,Y;
using namespace std;
const int MAXNUM=2e9;
vector<vector<int>> m(31,vector<int>(51,0)); 
//表明一个点到起点的最短距离 
vector<vector<int>>	visited(31,vector<int>(51,MAXNUM));
int bestNum=MAXNUM;
string bestStr="";
int d[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
string step[4]={"U","D","L","R"}; 
struct Node{
	int sum;
	string path;
	int x;
	int y; 
	vector<pair<int,int>>	nodeList;
	vector<vector<bool>> visited=vector<vector<bool>>(31,vector<bool>(51,false));
	Node(){
		
	}
};
class Comp{
	public:
		bool operator()(const Node &a,const Node &b){
			if(a.sum>b.sum){
				return true;
			}else if(a.sum==b.sum){
				
				return ((a.path.compare(b.path))>0);
			}else{
				return false;
			}
		}
}; 
bool check(int x,int y){
	return 1<=x&&x<=X&&1<=y&&y<=Y&&(m[x][y]==0);
}
//核心代码
void bfs(){
	//广度优先遍历
	priority_queue<Node,vector<Node>,Comp> minHeap;
	//放入第一个节点
	Node first=Node();
	first.path="";
	//表示当前点到起点的最短距离
	first.sum=0;
	first.x=first.y=1;
	minHeap.emplace(first);
	visited[1][1]=0;
	int x,y;
	int num=0;
	while(!minHeap.empty()){
		//非空不断的迭代
		Node head=minHeap.top();
		minHeap.pop();
		x=head.x;
		y=head.y;
		//先检查一下大小
		if(x==X&&y==Y){
			//到达出口 
			bestNum=head.sum;
			bestStr=head.path;
			num=1;
			return;
		} 
		if(head.sum>=bestNum)	break; 
		//上下左右
		for(int i=0;i<=3;i++){
			if(check(x+d[i][0],y+d[i][1])){
				
				//当前路径不是最短距离直接跳过 
				if((head.sum+1)>visited[x+d[i][0]][y+d[i][1]]) 	continue;
				//创建新节点
				Node newNode=Node();
				newNode.x=x+d[i][0];
				newNode.y=y+d[i][1];
				newNode.sum=head.sum+1;
				visited[newNode.x][newNode.y]=head.sum+1; 
				newNode.path=head.path+step[i];
				//插入堆中
				minHeap.emplace(newNode); 
			}
		}
	}
}
int main(int argc, char** argv) {
	fstream f;
	f.open("./test.txt",ios::in);
	string a;
	X=30;
	Y=50;
	for(int i=1;i<=X;i++){
		getline(f,a);
		for(int j=1;j<=Y;j++){
			if(a[j-1]=='0')	m[i][j]=0;
			else			m[i][j]=1;
		}
	}
	bfs();
	cout<<bestStr<<endl;
	return 0; 
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值