八连块问题

输入一个黑白图像(1表示黑色,0表示白色),统计八连块的个数。

八连块的定义:如果两个黑格子有公共边和公共顶点,则属于同一个八连块。


八连块问题_第1张图片

例如上图有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());
    }
}

图片来源:八连块_百度图片搜索

你可能感兴趣的:(八连块问题)