C++演算法——BFS
BFS我們稱之為寬搜,通常可以用於解決最短,最小問題。不同於深搜,寬搜每次先把同一層的遍歷一遍,若無正確答案再去遍歷下一層,因此不需要用到遞迴,只需要用到迴圈即可。
先來看一道經典例題:走迷宮
解決走迷宮問題,我們可以用程式來模擬一下走迷宮,但不同人走迷宮,我們通過程式可以在一個位置從上下左右去嘗試,直到找到正確答案。
解決走迷宮問題,我們可以用程式來模擬一下走迷宮,但不同人走迷宮,我們通過程式可以在一個位置從上下左右去嘗試,直到找到正確答案。但前提是向該方向走一步後,到達的點是否合法,因此要進行判斷。同時如果該點已經走過,那我們也不要再走一遍。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int , int> PII;
const int N = 110;
//g陣列用來儲存地圖,d陣列用來每一個點到起始點的距離
int g[N][N] , d[N][N];
int n , m;
//佇列,表示當前走到的點
PII q[N * N];
int bfs()
{
//定義隊頭隊尾
int hh = 0 , tt = 0;
//先把第一個點放入當前走的點
q[0] = {0 , 0};
//初始化d陣列,使每個點都沒涉足
memset(d , -1 , sizeof d);
//表示第0個點已經走過了
d[0][0] = 0;
//定義了每次的x和y的偏移量
int dx[4] = {-1 , 0 , 1 , 0};
int dy[4] = {0 , 1 , 0 , -1};
//
while( hh <= tt )
{
//取隊頭元素
PII t = q[hh ++ ];
for(int i = 0 ; i < 4 ; i++)
{
int x = t.first + dx[i];
int y = t.second + dy[i];
//判斷該點不超出範圍,可走並且沒走過
if( x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)
{
//到起始點的距離
d[x][y] = d[t.first][t.second] + 1;
//新點入列
q[ ++tt ] = {x , y};
}
}
}
return d[n - 1][m - 1];
}
int main()
{
cin >> n >> m;
for(int i = 0 ; i < n ; i++)
{
for(int j = 0 ; j < m ; j++) cin >> g[i][j];
}
cout << bfs() << endl;
return 0;
}
作者:阿柴
連結:https://www.acwing.com/activity/content/code/content/582768/
來源:AcWing
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
寬搜同樣總結起來就是:
(1)處理好已經遍歷的點
(2)注意同層之間的資料轉換關係
(3)一定要還原現場!
接下來來看一道難題
#include<bits/stdc++.h>
using namespace std;
int bfs( string start )
{
string end = "12345678x";
queue<string> q;
unordered_map< string , int > d;
q.push(start);
//startd的初始距離為0
d[start] = 0;
int dx[4] = {1 , 0 , -1 , 0};
int dy[4] = {0 , 1 , 0 , -1};
//若佇列未空,繼續搜尋
while( q.size() )
{
//取佇列的頭元素
auto t = q.front();
q.pop();
if( t == end ) return d[t];
//取出當前狀態的距離
int dis = d[t];
//找出x的位置
int k = t.find( 'x' );
//將x的位置轉化為二維陣列的下標
int x = k / 3 , y = k % 3;
for(int i = 0 ; i < 4 ; i++)
{
for(int j = 0 ; j < 4 ; j++)
{
//將x往四個方向移動
int a = x + dx[i] , b = y + dy[i];
//如果移動後的點沒有越界
if( a >= 0 && a < 3 && b >= 0 && b < 3 )
{
swap( t[k] , t[ a * 3 + b ] );
//如果當前狀態沒有被記錄
if( !d.count(t) )
{
//當前狀態為上一上一狀態的距離+1
d[t] = dis + 1;
//入隊
q.push(t);
}
//因為還要判斷下一次移動的狀態,所以要還原現場
swap( t[k] , t[ a * 3 + b ] );
}
}
}
}
return -1;
}
int main()
{
string start;
for(int i = 0 ; i < 9 ; i++)
{
char x;
cin >> x;
start += x;
}
cout << bfs(start) << endl;
return 0;
}
作者:阿柴
連結:https://www.acwing.com/activity/content/code/content/585447/
來源:AcWing
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
相關文章
- BFS演算法原理演算法
- 聊聊演算法——BFS和DFS演算法
- LeetCode C++ 1302. Deepest Leaves Sum【Tree/BFS/DFS】中等LeetCodeC++
- (BFS廣度優先演算法) 油田問題演算法
- JAVA圖搜尋演算法之DFS-BFSJava演算法
- 4、BFS演算法套路框架——Go語言版演算法框架Go
- bfs
- 【演算法】廣度/寬度優先搜尋(BFS)演算法
- leetcode刷題記錄:演算法(六)BFS&DFSLeetCode演算法
- 演算法競賽——BFS廣度優先搜尋演算法
- 廣度優先搜尋(BFS)思路及演算法分析演算法
- 深度DFS 和 廣度BFS搜尋演算法學習演算法
- BFS(模板)
- Java實現 藍橋杯 演算法提高 八數碼(BFS)Java演算法
- poj 3278 BFS
- 01BFS
- Count BFS Graph
- C++容器演算法C++演算法
- DAG bfs + dfs 126,
- 【BFS】poj 3414 Pots
- c++ 遞推演算法C++演算法
- POJ3414 Pots【BFS】
- UVA11624 Fire!【BFS】
- 【BFS】腐爛的橘子
- BFS/acm習題集ACM
- 找朋友(bfs常錯!!)
- BFS和Dijkstra結合
- BFS入門筆記筆記
- C++演算法 線段樹C++演算法
- 模式匹配kmp演算法(c++)模式KMP演算法C++
- C++實現Prim演算法C++演算法
- SPFA演算法模板(C/C++)演算法C++
- BFS洛谷P1135 奇怪的電梯(我的演算法學習之路)演算法
- 基本演算法——深度優先搜尋(DFS)和廣度優先搜尋(BFS)演算法
- 0演算法基礎學演算法 搜尋篇第二講 BFS廣度優先搜尋的思想演算法
- HDU2612 Find a way【BFS】
- 藍橋杯-長草(BFS)
- 快速排序演算法C++實現排序演算法C++