小晴天老师系列——可恶的墨水瓶(floodfill)

G - 小晴天老师系列——可恶的墨水瓶
Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)
Submit Status
Problem Description

小晴天老师正在备课,这时,可恶的墨水瓶突然自己打翻了!悲剧发生了!小晴天的备课稿都被墨水弄脏了。。。。
不过小晴天很乐观~这时他把他的一张纸分成n*m个格子,其中有一些格子被墨水涂黑了,有的没有。那么小晴天想知道,最大的一块联通的墨水块占多少个格子呢?
所谓的联通的即两个格子至少有一个公共顶点。
Input

多组数据,首先是一个正整数t(t<=20)
对于每组数据,先给出两个整数m.n(1<=n,m<=20)
然后是一个m行n列的01矩阵,若为1,则该格子被墨水染黑。
Output

对于每组数据,输出一个整数,表示最大被墨水染黑的连通格子数。
Sample Input

1
4 4
1 1 0 0
0 1 1 0
0 0 1 0
1 0 0 0
Sample Output

5

题目大意:找出最大的8连通块
分析:dfs。。。对每一个访问过的顶点要标记一个vis来避免重复访问,同时要避免越界,可以考虑在格子的周围绕一圈0来进行隔离。这个算法名字叫floodfill,洪水填充法?

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int m, n, g[25][25], vis[25][25];
int cnt, ans, d1[1000], d2[1000];
int dr[8] = {0, -1, 0, 1, -1, -1, 1, 1};
int dc[8] = {-1, 0, 1, 0, 1, -1, -1, 1};

void dfs(int r, int c) {
    if(r < 0 || r >= m || c < 0 || c >= n || g[r][c] == 0) return;
    else {
        cnt++;
        vis[r][c] = 1;
        for(int i = 0; i < 8; i++) {
            int x = r + dr[i];
            int y = c + dc[i];
            if(!vis[x][y]) {
                vis[x][y] = 1;
                dfs(x, y);
            }
        }
    }
}

int main() {
    int kase;
    scanf("%d", &kase);
    while(kase--) {
        int t = 0;
        scanf("%d%d", &m, &n);
        memset(g, 0, sizeof(g));
        memset(vis, 0, sizeof(vis));
        for(int i = 0; i < m; i++)
            for(int j = 0; j < n; j++) {
                scanf("%d", &g[i][j]);
                if(g[i][j] == 1) {
                    d1[t++] = i;
                    d2[t++] = j;
                }
            }
        ans = 0;
        for(int i = 0; i < t; i++) {
            if(!vis[d1[i]][d2[i]]) {
                cnt = 0;
                dfs(d1[i], d2[i]);
                ans = max(cnt, ans);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(DFS)