八连块问题

输入一个黑白图像(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());
    }
}

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

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容