#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
struct Sudoku {
private:
int blk[9], row[9], col[9];
int A[9][9], lg[1024];
int lowbit(int x) {
/// 得到最低二进制位
return x & (-x);
}
int BLK(int i, int j) {
/// 计算某个位置所在的块
return (i/3)*3 + (j/3);
}
std::vector<std::pair<int, int> > pos; /// 记录需要处理的位置
void DFS(int d) {
/// 填数
if(d == pos.size()) {
for(int i = 0; i <= 8; i ++) {
for(int j = 0; j <= 8; j ++) {
printf("%d ", A[i][j]);
}
putchar('\n');
}
putchar('\n');
}else {
int x = pos[d].first, y = pos[d].second;
int avai = row[x] & col[y] & blk[BLK(x, y)];
while(avai) {
int n = lowbit(avai); /// 找到最低比特并尝试
avai ^= n;
n = lg[n]; /// 找到对应的数字
A[x][y] = n;
blk[BLK(x, y)] ^= (1<<(n-1));
row[x] ^= (1<<(n-1));
col[y] ^= (1<<(n-1));
DFS(d + 1); /// 递归选择下一个位置
A[x][y] = 0;
blk[BLK(x, y)] ^= (1<<(n-1));
row[x] ^= (1<<(n-1));
col[y] ^= (1<<(n-1));
}
}
}
public:
Sudoku() {
for(int i = 1; i <= 9; i ++) {
/// 预处理取对数
lg[1<<(i-1)] = i;
}
for(int i = 0; i <= 8; i ++) {
blk[i] = row[i] = col[i] = 0;
}
for(int i = 0; i < 8; i ++) {
for(int j = 0; j < 8; j ++) {
A[i][j] = 0;
}
}
}
int Solve(int B[9][9]) {
/// B[i][j] = 0 表示该位置没有数
for(int i = 0; i <= 8; i ++) {
for(int j = 0; j <= 8; j ++) {
/// 坐标 [0, 8]
A[i][j] = B[i][j];
if(A[i][j] != 0) {
blk[BLK(i, j)] |= (1 << (A[i][j]-1));
row[i] |= (1 << (A[i][j]-1));
col[j] |= (1 << (A[i][j]-1)); /// 处理行列和块
/// col[j] 写成了 col[i] 调试了一天 qwq
}else {
pos.push_back(std::make_pair(i, j));
}
}
}
for(int i = 0; i <= 8; i ++) {
blk[i] = ((1<<9)-1) ^ blk[i]; /// 取反
row[i] = ((1<<9)-1) ^ row[i];
col[i] = ((1<<9)-1) ^ col[i];
}
DFS(0);
return 0;
}
};
int B[9][9];
int main() {
Sudoku* tmp = new Sudoku;
for(int i = 0; i <= 8; i ++) {
for(int j = 0; j<= 8; j ++) {
scanf("%d", &B[i][j]);
}
}
tmp -> Solve(B);
return 0;
}
位运算优化数独
猜你喜欢
转载自blog.csdn.net/GGN_2015/article/details/115348528
今日推荐
周排行