回溯法数独求解

匿名 (未验证) 提交于 2019-12-02 21:45:52
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();             }         }     } }

文章来源: 回溯法数独求解
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!