点击查看代码
#include <bits/stdc++.h>
using namespace std;
int a[10][10]; // 存数独地图
bool row[10][10], col[10][10], block[3][3][10]; // 三个记账本,标记题目要求的三个状态
// 打印函数
void print() {
for(int i=1; i<=9; i++) {
for(int j=1; j<=9; j++) cout << a[i][j] << " ";
cout << endl;
}
exit(0); // 填完一种方案就可以直接结束程序了,不用找所有解
}
//1.状态定义,就是棋盘的每个棋子的坐标
void dfs(int x, int y) {
//2.截止条件与换行逻辑,这里是相互统一的
//y到了一定地步才可以换行
if (y == 10) {
dfs(x + 1, 1);
return;
}
if (x == 10) {
print();
return;
}
//4.和下面的for循环算是枚举和选择的逻辑,不是剪枝,因为这是逻辑的必须
if (a[x][y] != 0) {
// 直接跳过,去填下一个
dfs(x, y + 1);
return;
}
for (int k = 1; k <= 9; k++) {
// 计算九宫格的坐标
int bx = (x - 1) / 3;
int by = (y - 1) / 3;
// 选择逻辑的一部分,三个标记
if (!row[x][k] && !col[y][k] && !block[bx][by][k]) {
//5.回溯三件套
// A. 标记 (Make Move)
a[x][y] = k;
row[x][k] = true;
col[y][k] = true;
block[bx][by][k] = true;
// B. 递归
dfs(x, y + 1);
// C. 回溯 (Unmake Move) - 非常重要!
a[x][y] = 0;
row[x][k] = false;
col[y][k] = false;
block[bx][by][k] = false;
}
}
}
int main() {
// 读入数据顺便标记这个数字对应的行列和九宫格的标记情况
for(int i=1; i<=9; i++) {
for(int j=1; j<=9; j++) {
cin >> a[i][j];
if(a[i][j] != 0) {
int k = a[i][j];
row[i][k] = true;
col[j][k] = true;
block[(i-1)/3][(j-1)/3][k] = true;
}
}
}
dfs(1, 1);
return 0;
}