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(); } } } }
文章来源: 回溯法数独求解