You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
3.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
const int N = 10;
int g[N][N]; // 棋盘
// 行,列,九宫格分别用的状态压缩桶
// 索引九宫格是0~8的索引
// 内容值1~9位状态压缩,0位没有用不用管它。
int r[N], c[N], w[N];
bool flag; // 是不是搜索到了第一个答案,如果是,则让其它搜索快速返回,剪一下枝
// 返回九宫格的编号
int get(int x, int y) {
x /= 3, y /= 3; // 注意两个都是/3表示是第几个小方块可以理解为0~8共9个小方块
return x * 3 + y; // 通过上面的变换映射到0~8数字上
}
// x,y这个坐标开始暴搜
// cnt:还有多少个点需要填充
void dfs(int x, int y, int cnt) {
if (flag) return; // 快速返回,剪枝
if (cnt == 0) { // 没有空格子了
// 输出答案
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
cout << g[i][j];
cout << endl;
// 修改第一次完成的标识
flag = true;
return;
}
int nx = x, ny = y + 1; // 下一个位置,默认是向右
if (ny == 9) nx++, ny = 0; // 越界了就从下一行开始
if (g[x][y] == 0) { // 如果此位置是空白
int u = get(x, y); // 这是第几号九宫格
for (int i = 1; i <= 9; i++) { // 尝试填充1~9
if (r[x] >> i & 1) continue;
if (c[y] >> i & 1) continue;
if (w[u] >> i & 1) continue;
// 修改状态,修改棋盘
r[x] += 1 << i, c[y] += 1 << i, w[u] += 1 << i, g[x][y] = i;
// 尝试下一个位置
dfs(nx, ny, cnt - 1);
// 恢复状态
r[x] -= 1 << i, c[y] -= 1 << i, w[u] -= 1 << i, g[x][y] = 0;
}
} else // 如果此位置不是空白,那么就尝试下一个位置
dfs(nx, ny, cnt);
}
int main() {
string str; // 输入的棋盘
while (cin >> str && str[0] != 'e') {
// 初始化
memset(g, 0, sizeof g); // 清空地图
memset(r, 0, sizeof r); // 清空行的标识
memset(c, 0, sizeof c); // 清空列的标识
memset(w, 0, sizeof w); // 清空9个小方块的标识
// 找到第一个方案的停止标识
flag = false;
// 记录需要填充的空位数量
int cnt = 0;
for (int i = 0; i < str.size(); i++) {
if (str[i] == '.') {
cnt++;
continue;
}
// 转换为行列坐标
int x = i / 9, y = i % 9; // x:行y:列
int u = get(x, y); // 0~8哪个九宫格
g[x][y] = str[i] - '0'; // 棋盘上放上数字
r[x] += 1 << g[x][y]; // 本质上是一个状态压缩,用二进制方式描述 x行上 g[x][y]这个数字的占用情况1表示已使用0表示未使用
c[y] += 1 << g[x][y]; // 列也用状态压缩描述
w[u] += 1 << g[x][y]; // 九宫格也用状态压缩描述
}
// 从左上角暴搜,cnt描述还有多少个位置需要搜索当cnt==0时停止
dfs(0, 0, cnt);
}
return 0;
}