输入一个黑白图像(1表示黑色,0表示白色),统计八连块的个数。
八连块的定义:如果两个黑格子有公共边和公共顶点,则属于同一个八连块。
例如上图有3个八连块。
本题属于图论中的计数问题,所以需要一个计数器。图形以二维数组的方式存储,遍历每个格子,如果是黑格子,依次访问它周围的黑格子,这样以DFS(深度优先搜索)的方式访问一个八连块。
public class EightBlocks {
private int[][] mat;
private int num = 0;
private int[][] vis; // 标记黑格子是否访问过,1表示访问过,0表示未访问
private final int x;
private final int y;
public EightBlocks(int[][] mat) {
this.mat = mat;
x = mat.length;
y = mat[0].length;
vis = new int[x][y];
}
private void dfs(int i, int j) {
// 可能存在数组越界,所以必须先检查是否越界
// 如果不想检查数组边界,可以在图像周围增加一圈白格子
if (i >= 0 && i < x && j >= 0 && j < y && mat[i][j] == 1 && vis[i][j] == 0) {
vis[i][j] = 1;
dfs(i - 1, j);
dfs(i + 1, j);
dfs(i, j - 1);
dfs(i, j + 1);
dfs(i + 1, j + 1);
dfs(i - 1, j - 1);
dfs(i - 1, j + 1);
dfs(i + 1, j - 1);
}
}
public int count() {
if(num > 0) {
return num;
}
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
if (mat[i][j] == 1 && vis[i][j] == 0) {
num++;
dfs(i, j);
}
}
}
return num;
}
public static void main(String[] args) {
int[][] mat = new int[][]{
{1, 0, 0, 1, 0, 0},
{0, 0, 1, 0, 1, 0},
{0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 0, 0},
{1, 1, 1, 0, 0, 0},
{0, 1, 0, 1, 0, 0}
};
EightBlocks eightBlocks = new EightBlocks(mat);
System.out.println("八连块个数:" + eightBlocks.count());
}
}
图片来源:八连块_百度图片搜索