BFS(廣度優先搜尋)記憶搜尋(二)
阿新 • • 發佈:2018-12-12
一提到BFS的時候大家一般都會申請一個數組vis,vis的作用是用來標記有沒有搜尋過,如果搜尋過那麼vis = 1,如果沒有搜尋過那麼vis = 0,在每一次搜尋的時候都會重新初始化vis, 把vis初始化為0,如果查詢的次數比較多,那麼就白白浪費了很多時間,很多的操作其實都是重複的,所以這篇部落格講述BFS+記憶搜尋。
大家在做BFS題的時候有沒有意識到其實BFS在搜尋的時候只是搜尋連通的某塊,就比如說你在一個荒島上,其他人在另外一個島上,你和其他人也沒有辦法取得聯絡,所以BFS的搜尋也是一個道題,BFS模組搜尋的其實只是互相連通模組,如果不互相連通那麼這些模組其實沒有任何關係,也就是不能相互到達。所以在記憶化搜尋時vis就不用每次初始化,一次就行,vis用來記錄可以相互到達的模組。在每次查詢的時候只要先詢問是否被分配到一個模組中,如果沒有在就用BFS查詢,如果有直接就知道這個模組的中幾個點可以相互到達。
01迷宮 洛谷 P1141
題意:有一個僅由數字00與11組成的n×n格迷宮。若你位於一格0上,那麼你可以移動到相鄰44格中的某一格11上,同樣若你位於一格1上,那麼你可以移動到相鄰44格中的某一格00上。你的任務是:對於給定的迷宮,詢問從某一格開始能移動到多少個格子(包含自身)。
題解:題意很簡單,但是查詢的次數比較多,如果只用最普通的查詢那麼這道題會直接TLE的,一開始我就直接普通的BFS演算法,但是隻通過了70%,其中有三個直接TLE,有三個點的資料太大,不適合直接查詢,所以需要BFS+記憶化,只要某些點在同一個某塊中這些點就可以相互到達。
這個是一開始大程式碼
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<queue> using namespace std; #define N 1005 struct Node{ int x, y; char pre; }tmp1, tmp2; char a[N][N]; int n, step; int dx[8]={1,-1,0,0}; int dy[8]={0,0,1,-1,}; int vis[N][N]; void bfs(int st, int en){ memset(vis, 0, sizeof(vis)); step = 0; tmp1.x = st; tmp1.y = en; vis[st][en]= 1; tmp1.pre = a[st][en]; queue<Node>q; q.push(tmp1); while(!q.empty()){ tmp1 = q.front(); q.pop(); //cout<<tmp1.x<<" "<<tmp1.y<<endl; for(int i = 0; i < 8; i++){ tmp2.x = tmp1.x + dx[i]; tmp2.y = tmp1.y + dy[i]; if(tmp2.x >= 0 && tmp2.x<n && tmp2.y>= 0&&tmp2.y < n && !vis[tmp2.x][tmp2.y]&& a[tmp2.x][tmp2.y]!=tmp1.pre){ vis[tmp2.x][tmp2.y] = 1; tmp2.pre = a[tmp2.x][tmp2.y]; q.push(tmp2); step++; } } } } int main(){ int m, st, en; cin>>n>>m; for(int i = 0; i < n; i++){ scanf("%s", a[i]); } while(m--){ cin>>st>>en; bfs(st-1, en-1); cout<<step+1<<endl; } return 0; }
這個是AC程式碼
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<queue> using namespace std; #define N 1005 #define maxn 1000005 struct Node { int x, y; char pre; } tmp1, tmp2; char a[N][N]; int n, num = 0; int dx[8]= {1,-1,0,0}; int dy[8]= {0,0,1,-1,}; int vis[N][N]; int ans[maxn]; int bfs(int st, int en) { num++; int step = 1; tmp1.x = st; tmp1.y = en; vis[st][en]= num; tmp1.pre = a[st][en]; queue<Node>q; q.push(tmp1); while(!q.empty()) { tmp1 = q.front(); q.pop(); for(int i = 0; i < 8; i++) { tmp2.x = tmp1.x + dx[i]; tmp2.y = tmp1.y + dy[i]; if(tmp2.x >= 0 && tmp2.x<n && tmp2.y>= 0&&tmp2.y < n && !vis[tmp2.x][tmp2.y]&& a[tmp2.x][tmp2.y]!=tmp1.pre) { vis[tmp2.x][tmp2.y] = num; tmp2.pre = a[tmp2.x][tmp2.y]; q.push(tmp2); step++; } } } ans[num] = step; return step; } int main() { int m, st, en; cin>>n>>m; for(int i = 0; i < n; i++) { scanf("%s", a[i]); } while(m--) { cin>>st>>en; if(!vis[st-1][en-1])//查詢是否在一個模組中 cout<<bfs(st-1, en-1)<<endl; else cout<<ans[vis[st-1][en-1]]<<endl; } return 0; }