数独计算程序
数独是什么,就不解释了。
下面给出一个数独的截图
计算规则,其实对每个未确定的空格,保证所在的行唯一,列唯一和所在小九宫格唯一就好了。
直观的解决方法是暴力+回溯。
但是暴力+回溯可能带来的问题是,效率不高。
实际计算过程中,可以进行剪枝,即去除一部分无效运算。则面临2个问题。
1. 如何确定下一个对象。 即有这么多需要确定的空格,如何确定那些空格的优先级
2. 在面临每个空格都有多个选择的时候,如何选择。
上述两个问题是我们剪枝的原则。
对于上述数独。我们可以定义一个模型为:
class SudokuInstance{ SudokuCell[][] cells; public SudokuInstance(int[][] sudoku){ init(sudoku); } void init(int[][] sudoku){ initCells(sudoku); adjustCells(); } void initCells(int[][] sudoku){ cells = new SudokuCell[9][9]; for(int i=0;i<sudoku.length;i++){ for(int j=0;j<sudoku.length;j++){ if(sudoku[i][j] == 0){ cells[i][j] = new SudokuCell(i,j,sudoku[i][j]); }else{ cells[i][j] = new SudokuCell(i,j); } } } void adjustCells(){ //1. reduceCandidates //2. checkFamliyUnique() } } public static class SudokuCell{ private int x; private int y; private List<Integer> candidates; private int val; private SudokuFamliy famliy; public SudokuCell(int x,int y, int val){ this.x=x; this.y=y; this.val=val; this.candidates=new LinkedList<>(); this.famliy = SudokuFamliy.vauleOf(x,y); } public SudokuCell(int x,int y, int val){ this.x=x; this.y=y; this.candidates=new LinkedList<>(); for(int i=1;i<10;i++){ this.candidates.add(i); } this.famliy = SudokuFamliy.vauleOf(x,y); } } }
模型定义好以后,后续主要是调整堆栈。以及剪枝策略。
剪枝策略是选出候选最少的进行枚举。