1. 程式人生 > >用dfs遍歷聯通塊(優化)

用dfs遍歷聯通塊(優化)

name ios while 題目 har color pan 多少 一個

一、題目(CF 598D)

輸入一個n x m的字符矩陣,求從某個空點出發,能碰到多少面墻壁,總共詢問k次。(3 ≤m,n ≤1000,1 ≤ k ≤ min(nm,100 000))

二、解題思路

用DFS找連通分量:從每個“.”格子出發,遞歸遍歷與之相鄰的“*”格子,且寫上相同的聯通分量(即代碼中的blocks數組),同時統計該聯通分量邊界墻壁面數。由於存在多次查詢,我們用blocks[i][j]記錄格子(i,j)所在的聯通分量標號,用res[i]表示聯通分量i的邊界墻壁面數。

三、代碼實現

 1 #include<stdio.h>
 2 #include<iostream>
 3
#include<string.h> 4 #include<stdbool.h> 5 using namespace std; 6 7 const int maxn = 1000 + 10; 8 const int maxm = 1000 + 10; 9 const int maxk = 100000 + 10; 10 const int maxx = 1000000 + 10; 11 int n, m; 12 char maze[maxn][maxm]; 13 bool vis[maxn][maxm]; 14 int blocks[maxn][maxm]; 15 int res[maxx]; 16
int dx[] = { -1,0,1,0 }, dy[] = { 0,1,0,-1 }; 17 int flag = 0; 18 19 void dfs(int x, int y, int flag,int& sum) //sum傳引用 20 { 21 vis[x][y] = true; 22 blocks[x][y] = flag; 23 for (int i = 0; i < 4; i++) 24 { 25 int xx = x + dx[i]; int yy = y + dy[i]; 26 if (xx >= 0 && xx < n && yy >= 0
&& yy < m && (!vis[xx][yy])) 27 { 28 if (maze[xx][yy] == *) 29 sum++; 30 else 31 dfs(xx, yy, flag,sum); 32 } 33 } 34 } 35 int main() 36 { 37 int k; 38 scanf("%d%d%d", &n, &m, &k); 39 memset(vis, 0, sizeof(vis)); 40 41 for (int i = 0; i < n; i++) 42 for (int j = 0; j < m; j++) 43 cin >> maze[i][j]; 44 45 for (int i = 0; i < n; i++) 46 for (int j = 0; j < m; j++) 47 { 48 if (maze[i][j] == . && (!vis[i][j])) 49 50 { 51 int sum = 0; 52 dfs(i, j, ++flag,sum); 53 res[flag] = sum; 54 } 55 } 56 57 while (k--) 58 { 59 int sx, sy; 60 scanf("%d%d", &sx, &sy); 61 printf("%d\n", res[blocks[sx - 1][sy - 1]]); 62 } 63 return 0; 64 }

用dfs遍歷聯通塊(優化)