zoukankan      html  css  js  c++  java
  • 回溯法数独求解

    public class SoduTest {
        private int[][] sodu = {
                // 最难的
    //            {0,0,5,3,0,0,0,0,0},
    //            {8,0,0,0,0,0,0,2,0},
    //            {0,7,0,0,1,0,5,0,0},
    //            {4,0,0,0,0,5,3,0,0},
    //            {0,1,0,0,7,0,0,0,6},
    //            {0,0,3,2,0,0,0,8,0},
    //            {0,6,0,5,0,0,0,0,9},
    //            {0,0,4,0,0,0,0,3,0},
    //            {0,0,0,0,0,9,7,0,0}
    
                // 包含两个解的
                {7,6,1,2,4,5,8,3,9},
                {3,2,8,1,7,9,4,5,6},
                {0,0,4,8,3,6,7,2,1},
                {8,7,5,9,6,4,2,1,3},
                {2,3,9,7,5,1,6,4,8},
                {1,4,6,2,8,3,9,7,5},
                {4,1,7,3,9,8,5,6,2},
                {0,0,3,4,2,6,1,8,7},
                {6,8,2,5,1,7,3,9,4}
        };
        public static void main(String[] args) {
            long timeStart = System.currentTimeMillis();
            new SoduTest().getSoduAnswer(0, 0);
            long timeStop = System.currentTimeMillis();
            System.out.println("It took " + (timeStop - timeStart) + " milliseconds");
        }
    
        /**
         * 核心算法,利用递归回溯,求出所有解
         * @param x 起始第 x 行
         * @param y 起始第 y 列
         * @return
         */
        private boolean getSoduAnswer(int x, int y) {
            if(y == 9) {
                // 终止条件
                if(x == 8) {
                    // 打印
                    printSodu(this.sodu);
                    System.out.println("-------------------------------------------");
                    // 若返回true,则求出一个解后退出
    //                return true;
                    // 若返回false,则求出一个解后向前回溯,直到求出所有解
                    return false;
                }
                // 换行
                x++;
                y = 0;
            }
            // 如果不为0,直接计算下一个数
            if(this.sodu[x][y] != 0) {
                return getSoduAnswer(x, y+1);
            }
            // 尝试 1-9 是否满足条件
            for(int i = 1; i <= 9; i++) {
                if(this.checkSoduNum(x, y, i)) {
                    //满足条件设置值
                    this.sodu[x][y] = i;
                    //并尝试下一个数是否满足条件
                    if(getSoduAnswer(x, y+1)) {
                        return true;
                    }else {
                        // 若不满足条件,进行回溯
                        this.sodu[x][y] = 0;
                    }
                }
            }
            return false;
        }
    
        /**
         * 判断值是否合理
         * @param x
         * @param y
         * @param soduNum
         * @return
         */
        private boolean checkSoduNum(int x, int y, int soduNum) {
            // 判断当前行,列是否有重复
            for(int i = 0;i < 9;i++) {
                if(this.sodu[x][i] == soduNum) {
                    return false;
                }
                if(this.sodu[i][y] == soduNum) {
                    return false;
                }
            }
            // 求出左上角坐标
            int a = x - (x % 3);
            int aStop = a+3;
            int b = y - (y % 3);
            int bStop = b+3;
            // 判断当前方框内是否有重复
            for(a = x - (x % 3);a<aStop;a++) {
                for(b = y - (y % 3);b<bStop;b++) {
                    if(this.sodu[a][b] == soduNum) {
                        return false;
                    }
                }
            }
            return true;
        }
    
        /**
         * 打印数组
         * @param sodu
         */
        public static void printSodu(int[][] sodu) {
            for(int i = 0; i < sodu.length; i++) {
                int[] soduX = sodu[i];
                for(int j = 0; j < soduX.length; j++) {
                    int soduY = soduX[j];
                    if(j != 0 && j % 3 == 0) {
                        System.out.print(" ");
                    }
                    System.out.print(soduY);
                }
                System.out.println();
                if(i != 0 && (i+1) % 3 == 0) {
                    System.out.println();
                }
            }
        }
    }
  • 相关阅读:
    Typora使用腾讯云图床
    2020年8月总结
    113 路径之和II
    103 二叉树的锯齿形层次遍历
    128 最长连续序列
    160 相交链表
    33 搜索旋转排序数组
    学习制作GitHub徽标
    105 从前序与中序遍历序列构造二叉树
    重新封装了layer.tips,自定义跟随弹窗
  • 原文地址:https://www.cnblogs.com/gode/p/11039367.html
Copyright © 2011-2022 走看看