数独

public class SudokuDemo {
    public static void main(String[] args) {
        // 数独
        sudoku();
    }

    public static void sudoku() {
        long start = System.currentTimeMillis();

        int[][] num = { { 0, 5, 7, 0, 0, 0, 0, 0, 0 },
                              { 0, 0, 0, 0, 4, 7, 0, 0, 0 }, 
                              { 0, 0, 0, 0, 8, 0, 0, 6, 2 },
                              { 7, 0, 0, 0, 0, 0, 9, 1, 0 }, 
                              { 3, 0, 5, 6, 0, 0, 0, 0, 0 },
                              { 0, 1, 0, 0, 0, 0, 0, 8, 0 }, 
                              { 0, 0, 8, 0, 0, 9, 0, 0, 1 },
                              { 0, 0, 4, 0, 0, 2, 3, 0, 9 }, 
                              { 0, 6, 0, 0, 0, 0, 8, 0, 0 } };
        int x = 0, y = 0;

        int r = ans(num, x, y);

        long end = System.currentTimeMillis();

        System.out.println("一共耗时 " + (end - start) + " ms");

        if (r != 0) {
            System.out.println("没有解。。。");
            return;
        }

        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                System.out.print(num[i][j] + " ");
            }
            System.out.println();
        }
    }

    private static int ans(int[][] num, int x, int y) {
        if (x >= 9 || y >= 9) {
            return 0;
        }

        // 查找对应的空白域
        if (num[x][y] != 0) {
            // 下一个空白域
            int[] curPos = nextEmptyPos(num, x, y);
            if (curPos[0] >= 9) {
                return 0;
            }
            x = curPos[0];
            y = curPos[1];
        }

        for (int rs = 1; rs <= 9; rs++) {
            // 检查横、竖
            if (!checkHorizontalOrVertical(num, rs, x, y)) {
                continue;
            }
            // 内部9宫格
            if (!checkInnerNine(num, rs, x, y)) {
                continue;
            }

            // 目标值
            num[x][y] = rs;

            // 下一个空白域
            int[] next = nextEmptyPos(num, x, y);
            if (next[0] >= 9) {
                return 0;
            }
            int nx = next[0], ny = next[1];

            // 下一个值
            int r = ans(num, nx, ny);

            // 没找到,复位,回溯
            if (r == -1) {
                num[x][y] = 0;
                continue;
            }

            // 结束
            if (r == 0) {
                return 0;
            }
        }

        // 没找到,回溯
        return -1;
    }

    private static boolean checkHorizontalOrVertical(int[][] num, int target,
            int x, int y) {
        for (int i = 0, j = 0; i < 9 || j < 9; i++, j++) {
            if (target == num[x][i] || target == num[j][y]) {
                return false;
            }
        }
        return true;
    }

    private static boolean checkInnerNine(int[][] num, int target, int x,
            int y) {
        int offsetX = x / 3, offsetY = y / 3;
        int startX = offsetX * 3, startY = offsetY * 3;
        int endX = startX + 3, endY = startY + 3;
        for (int i = startX, j = startY; i < endX; j++) {
            if (target == num[i][j]) {
                return false;
            }
            // 内部9宫格下一行
            if (endY - 1 == j) {
                i++;
                j = startY - 1;
            }
        }
        return true;
    }

    private static int[] nextEmptyPos(int[][] num, int x, int y) {
        do {
            y++;
            if (y >= 9) {
                x++;
                y = 0;
            }
        } while (x < 9 && num[x][y] != 0);
        return new int[] { x, y };
    }

}

 

posted @ 2022-06-24 19:46  黎明的星海  阅读(51)  评论(0编辑  收藏  举报