1. 程式人生 > >BFS(廣度優先搜尋)記憶搜尋(二)

BFS(廣度優先搜尋)記憶搜尋(二)

  一提到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;
}