對於聯通塊的處理
阿新 • • 發佈:2018-03-02
輸入格式 spa 集合 with 開始 接下來 重點 using false
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; }
對於聯通塊的處理