標籤:empty queue 維護 exist 這一 開始 集合 cin inpu
01迷宮題目描述
有一個僅由數字0與1組成的n×n格迷宮。若你位於一格0上,那麼你可以移動到相鄰4格中的某一格1上,同樣若你位於一格1上,那麼你可以移動到相鄰4格中的某一格0上。
你的任務是:對於給定的迷宮,詢問從某一格開始能移動到多少個格子(包含自身)。
輸入輸出格式輸入格式:
輸入的第1行為兩個正整數n,m。
下面n行,每行n個字元,字元只可能是0或者1,字元之間沒有空格。
接下來m行,每行2個用空格分隔的正整數i,j,對應了迷宮中第i行第j列的一個格子,詢問從這一格開始能移動到多少格。
輸出格式:
輸出包括m行,對於每個詢問輸出相應答案。
輸入輸出範例輸入範例:
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$。
對於這一到搜尋題,怎麼搜尋不是重點,重點是如何處理一個個聯通塊。
對於滿分資料,每次詢問遍曆一邊的是不可能的,這輩子都是不可能的。
我們可以染色或用並查集維護集合
這一道題它啟示我們,在處理擁有同一個性質的聯通塊時,要整塊整塊的處理
#include<iostream>#include<queue>using namespace std;int dp[1010][1010],map[1010][1010];bool exist[1010][1010];int dx[4]={0,0,-1,1};int dy[4]={-1,1,0,0};int n,m,z;queue<int>ox;queue<int>oy;int find(int x,int y){ if(exist[x][y]) return dp[x][y]; exist[x][y]=true; int lx,ly; ox.push(x);oy.push(y); z++; for(int i=0;i<4;i++) { lx=x+dx[i];ly=y+dy[i]; if(lx>0&&lx<=n&&ly>0&&ly<=n&&!exist[lx][ly]&&map[lx][ly]!=map[x][y]) find(lx,ly); } return dp[x][y];}int main(){ cin.sync_with_stdio(false); cin>>n>>m; char input; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { cin>>input; map[i][j]=input-‘0‘; dp[i][j]=1; } int a,b; for(int i=1;i<=m;i++) { cin>>a>>b; find(a,b); z=max(z,dp[a][b]); cout<<z<<endl; while(!ox.empty()) { dp[ox.front()][oy.front()]=z; ox.pop();oy.pop(); } z=0; } return 0;}
對於聯通塊的處理