蓝桥杯——迷宫(BFS)

  • 思路
    迷宫问题本质是一个最短路径问题。对于最短路径问题一般使用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; 
}


猜你喜欢

转载自blog.csdn.net/qq_33880925/article/details/129583415