数独
这是求解数独的程序。还是深搜。
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;
}
浙公网安备 33010602011771号