題目描述
有一個僅由數字0與1組成的n×n格迷宮。若你位於一格0上,那麼你可以移動到相鄰4格中的某一格1上,同樣若你位於一格1上,那麼你可以移動到相鄰4格中的某一格0上。
你的任務是:對於給定的迷宮,詢問從某一格開始能移動到多少個格子(包含自身)。
輸入輸出格式
輸入格式:
輸入的第1行爲兩個正整數n,m。
下面n行,每行n個字符,字符只可能是0或者1,字符之間沒有空格。
接下來m行,每行2個用空格分隔的正整數i,j,對應了迷宮中第i行第j列的一個格子,詢問從這一格開始能移動到多少格。
輸出格式:
輸出包括m行,對於每個詢問輸出相應答案。
輸入輸出樣例
輸入樣例#1:
2 2
01
10
1 1
2 2
輸出樣例#1:
4
4
說明
所有格子互相可達。
對於20%的數據,n≤10;
對於40%的數據,n≤50;
對於50%的數據,m≤5;
對於60%的數據,n≤100,m≤100;
對於100%的數據,n≤1000,m≤100000。
果然是比較入門的BFS,適合退役大半年的我復出。。。
加個優化:因爲同一路線任意一點延展路徑固定,所以我們保存以前路線,下次掃描時判斷。
另一種思路:可以用連通塊維護並查集,輸出該方格所在的聯通快的點(然而我都忘了怎麼寫並查集···)
代碼如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=1005,dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
struct node
{
int x,y;
}x;
bool a[N][N];
int vis[N][N],n,m,n1=0,rec[N*N];
int bfs(node b)
{
int s=0,i,fx,fy;
node t,r;
queue<node>q;
q.push(b);
vis[b.x][b.y]=n1;
while(!q.empty())
{
r=q.front();
q.pop();
s++;
for(i=0;i<4;i++)
{
fx=r.x+dx[i];
fy=r.y+dy[i];
if(fx>=1&&fx<=n&&fy>=1&&fy<=n&&a[r.x][r.y]!=a[fx][fy]&&!vis[fx][fy])
{
t.x=fx;
t.y=fy;
vis[t.x][t.y]=n1;
q.push(t);
}
}
}
return s;
}
int main()
{
int i,j;
char c;
ios::sync_with_stdio(false);
cin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
cin>>c;
a[i][j]=c-'0';
}
for(i=1;i<=m;i++)
{
cin>>x.x>>x.y;
if(vis[x.x][x.y])
cout<<rec[vis[x.x][x.y]]<<endl;
else
{
n1++;
rec[n1]=bfs(x);
cout<<rec[n1]<<endl;
}
}
return 0;
}