数独是什么,就不解释了。
下面给出一个数独的截图
计算规则,其实对每个未确定的空格,保证所在的行唯一,列唯一和所在小九宫格唯一就好了。
直观的解决方法是暴力+回溯。
但是暴力+回溯可能带来的问题是,效率不高。
实际计算过程中,可以进行剪枝,即去除一部分无效运算。则面临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);
}
}
}
模型定义好以后,后续主要是调整堆栈。以及剪枝策略。
剪枝策略是选出候选最少的进行枚举。