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;
}