01迷宫(BFS+记忆)
生活随笔
收集整理的這篇文章主要介紹了
01迷宫(BFS+记忆)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述
有一個僅由數字 0 與 1 組成的 n × n 格迷宮。若你位于一格 0 上,那么你可以移動到相鄰 4 格中的某一格 1 上,同樣若你位于一格 1 上,那么你可以移動到相鄰 4 格中的某一格 0 上。
你的任務是:對于給定的迷宮,詢問從某一格開始能移動到多少個格子(包含自身)。
輸入
輸入的第 1 行為兩個正整數 n,m (n ≤ 1000,m ≤ 100000)
下面 n 行,每行 n 個字符,字符只可能是 0 或者 1,字符之間沒有空格。
接下來 m 行,每行 2 個用空格分隔的正整數 i,j,對應了迷宮中第 i 行第 j 列的一個格子,詢問從這一格開始能移動到多少格。
輸出
輸出包括 m 行,對于每個詢問輸出相應答案。
樣例輸入
2 2
01
10
1 1
2 2
樣例輸出
4
4
分析
- 一般看到這道題都會第一時間想到直接暴力搜索。是的沒錯,無論是DFS還是BFS都能幫我們找到結果,但是現在的問題就在于m的取值。若m取到極限值100000,我們真的要去搜十萬次,肯定會TLE,怎么解決這個問題呢?
- 我們仔細想想,如果迷宮中A、B兩格是相通的,那么我們是不是就可以從A走到B,也可以從B走到A。由此我們可以想到,如果迷宮中的某一塊是連通的,那么在這一塊中的任意一格,它們能移動到的格子數是相同的!!
- 因此我們可以在一次搜索中,把這次能走到的格子都做上標記,當下一次要搜索這些格子時,直接用上一次的結果。(記憶化)
代碼如下:
#include <iostream> #include <cstring> #include <queue> using namespace std; struct point{int x,y;point(int a,int b):x(a),y(b){} }; const int maxn=1000+5; char smap[maxn][maxn];//存儲地圖 int d[8]={0,1,0,-1,1,0,-1,0}; int mem[maxn][maxn];//給搜索過的位置作標記 int n,m,i,j; int ans[maxn*100]={0};//存儲第t次搜索的結果 int bfs(int x,int y,int t)//t表示第幾次搜索 {int cou=1;queue<point> q;point p(x,y);q.push(p);while(!q.empty()){p=q.front();//cout<<p.x<<" "<<p.y<<endl;q.pop();for(i=0;i<8;i+=2){int tx=p.x+d[i];int ty=p.y+d[i+1];if(tx>0&&tx<=n&&ty>0&&ty<=n&&smap[p.x][p.y]!=smap[tx][ty]&&mem[tx][ty]==0){point p1(tx,ty);q.push(p1);mem[tx][ty]=t;cou++;}}}return cou; } int main() {cin>>n>>m;for(i=1;i<=n;i++)cin>>smap[i]+1;for(int k=1;k<=m;k++){int x,y;cin>>x>>y;if(!mem[x][y])//如果該格子沒有被搜索過,就要搜索一遍{mem[x][y]=k;ans[k]=bfs(x,y,k);cout<<ans[k]<<endl;}else//被搜索過的話,直接輸出結果{int t=mem[x][y];ans[m]=ans[t];cout<<ans[m]<<endl;}}return 0; }
最后再附上簡單的bfs的模板
template <class T> void bfs(T a)//有沒有返回值看情況 {queue<T> q;q.push(a);while(!q.empty()){T p=q.front();//用一個臨時變量存儲隊列的第一份元素q.pop();for(i=0;i<8;i+=2)//在目前這點的四周移動{T temp = p+dx[i];//移動操作if(temp in the map&& no visit)//移動后的點,在地圖內,而且還沒有被訪問過{point p1(tx,ty);q.push(p1);memory[][]=true;//訪問過的點進行標記}}//通過一次循環操作,能把周圍的能到達的點都壓進隊列} }總結
以上是生活随笔為你收集整理的01迷宫(BFS+记忆)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图:BFS(深度优先搜索)图解分析代码实
- 下一篇: Firetruck(DFS+回溯)