思路 迷宫问题本质是一个最短路径问题。对于最短路径问题一般使用bfs+堆(先广搜索)
而不会用dfs
。因为dfs需要反复回溯,时间复杂度很高,而bfs
每个节点只需要遍历一次,时间复杂度为O(n)
(不算堆排序)。
bfs求最短路劲的原理 bfs求最短路径的思路是每轮遍历都求出当前节点到起点的最短距离,如果发现节点的最短距离已经求过那么就不用再遍历这个节点。由于再bfs+堆
中每个节点第一次被遍历到时它的权重就是起点到该节点的最短距离,所以实际上对于一张图每个节点只需遍历一次。bfs+堆
能保证每个遍历到的节点的距离都是最小是基于以下这个事实: 起点到节点 i 的最短距离 = m i n ( 起点到 i 的邻接点最短距离 ) + 1 起点到节点i的最短距离=min(起点到i的邻接点最短距离)+1 起点到节点 i 的最短距离 = min ( 起点到 i 的邻接点最短距离 ) + 1
迷宫问题模板
题目
核心代码
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) ;
}
}
}
}
模板
# include <iostream>
# 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 ;
}