数独
这是求解数独的程序。还是深搜。
class Sudoku { int table[9][9]; bool occupied[9][9][9]; int solution[9][9]; public: Sudoku(int* tab = 0) { set(tab); } void set(int* tab) { if (!tab) return; for (int i = 0; i < 81; ++i) table[i/9][i%9] = tab[i]; init(); } int solve() { int cnt = 0; solve(count(), cnt); return cnt; } bool solved() { bool r = true; for (int i = 0; r && i < 9; ++i) for (int j = 0; r && j < 9; ++j) if (!solution[i][j]) r = false; return r; } bool valid() { int i, j; return select(i, j); } void print(ostream& os) { for (int i = 0; i < 9; ++i) { if (!(i%3)) os<<"-------------------------\n"; for (int j = 0; j < 9; ++j) { if (!(j%3)) os<<"| "; os<<solution[i][j]<<' '; } os<<"|\n"; } os<<"-------------------------\n"; } private: int count() { int n = 0; for (int i = 0; i < 9; ++i) for (int j = 0; j < 9; ++j) if (!table[i][j]) ++n; return n; } bool solve(int n, int& cnt) { if (!n) { ++cnt; for (int i = 0; i < 9; ++i) for (int j = 0; j < 9; ++j) solution[i][j] = table[i][j]; return true; } if (cnt > 1) return true; int i = -1, j = -1; if (select(i, j)) { bool oldvalue[9][9]; for (int k = 0; cnt < 2 && k < 9; ++k) { if (occupied[i][j][k]) continue; table[i][j] = k + 1; update(i, j, true, oldvalue); solve(n-1, cnt); update(i, j, false, oldvalue); } table[i][j] = 0; } return cnt > 0; } void update(int i, int j, bool value, bool oldvalue[][9]) { if (value) { for (int ii = 0; ii < 9; ++ii) for (int jj = 0; jj < 9; ++jj) oldvalue[ii][jj] = occupied[ii][jj][table[i][j]-1]; for (int k = 0; k < 9; ++k) { occupied[i][k][table[i][j]-1] = value; occupied[k][j][table[i][j]-1] = value; } int gi = i/3, gj = j/3; for (int p = 0; p < 3; ++p) { int iii = gi*3 + p; for (int q = 0; q < 3; ++q) { int jjj = gj*3 + q; occupied[iii][jjj][table[i][j]-1] = value; } } } else { for (int ii = 0; ii < 9; ++ii) for (int jj = 0; jj < 9; ++jj) occupied[ii][jj][table[i][j]-1] = oldvalue[ii][jj]; } } int occupy(int i, int j) { int cmin = 0; for (int k = 0; k < 9; ++k) if (!occupied[i][j][k]) ++cmin; return cmin; } bool select(int& i, int& j) { int min = 10, mini, minj; for (int ii = 0; ii < 9; ++ii) { for (int jj = 0; jj < 9; ++jj) { if (table[ii][jj]) continue; int cmin = occupy(ii, jj); if (!cmin) return false; if (cmin < min) { min = cmin; mini = ii; minj = jj; } } } if (min < 10) { i = mini; j = minj; return true; } return false; } void init() { for (int i = 0; i < 9; ++i) for (int j = 0; j < 9; ++j) { for (int k = 0; k < 9; ++k) occupied[i][j][k] = false; solution[i][j] = 0; } bool oldvalue[9][9]; for (int i = 0; i < 9; ++i) for (int j = 0; j < 9; ++j) if (table[i][j]) update(i, j, true, oldvalue); } }; int main() { Sudoku sudoku; int table[81]; while (1) { bool in = true; int i = 0; for (; in && i < 81; ++i) in = !!(cin>>table[i]); if (!in || i < 81) break; sudoku.set(table); if (sudoku.valid()) { int cnt = sudoku.solve(); if (cnt == 1) sudoku.print(cout); else if (cnt == 0) cout<<"Case not solvable.\n"; else cout<<"Case has multiple solutions.\n"; } else cout<<"Case not valid.\n"; } return 0; }