版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/84034211
思路分析:
使用DFS, 每次选择当前可填方案最少的空格对应分支进行递归, 并使用位运算进行优化, 需要注意的是如果不预先哈希lowblt将会TLE, 下面给出AC代码:
//POJ3074_Sudoku
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int G[10][10], fix[10][10], R[10], C[10], A[10], ah[10][10], findd, cnt;
int lb[1 << 9];//lb[i]:i中1的个数
int lowbit(int a){
int ans = 0; while(a) a -= a & -a, ++ans; return ans;
}
//计算当前可选填数方案最少的空格
pair<int, int> getMin(){
int resx, resy, t = 10, f;
for(int i = 1; i <= 9; ++i)
for(int j = 1; j <= 9; ++j)
if(!fix[i][j] && !G[i][j] && (f = lb[R[i] & C[j] & A[ah[i][j]]]) < t)
t = f, resx = i, resy = j;
return make_pair(resx, resy);
}
void dfs(int x, int y){
if(cnt == 81){
for(int i = 1; i <= 9; ++i)
for(int j = 1; j <= 9; ++j) cout << G[i][j];
cout << endl, findd = 1; return;
}
for(int i = 1, k = ah[x][y], t = R[x] & C[y] & A[k]; i <= 9; ++i)
if(t >> i - 1 & 1){
G[x][y] = i, R[x] ^= 1 << i - 1, C[y] ^= 1 << i - 1, A[k] ^= 1 << i - 1, ++cnt;
pair<int, int> nex = getMin(); dfs(nex.first, nex.second); if(findd) return;
G[x][y] = 0, R[x] ^= 1 << i - 1, C[y] ^= 1 << i - 1, A[k] ^= 1 << i - 1, --cnt;
}
}
int main(){
char cstr[100]; for(int i = 1; i < 1 << 9; ++i) lb[i] = lowbit(i);
while(scanf("%s", cstr + 1), cstr[1] != 'e'){
memset(G, 0, sizeof(G)), memset(fix, 0, sizeof(fix)), findd = 0, cnt = 0;
for(int i = 1; i <= 9; ++i) R[i] = C[i] = A[i] = (1 << 9) - 1;
for(int i = 1; i <= 9; ++i){
for(int j = 1; j <= 9; ++j){
int k = cstr[(i - 1) * 9 + j] == '.'? 0: cstr[(i - 1) * 9 + j] - '0';
G[i][j] = k, ah[i][j] = 3 * (i / 3 - !(i % 3) * 1) + j / 3 + 1 - !(j % 3) * 1;
if(k)
fix[i][j] = 1, R[i] ^= 1 << k - 1, C[j] ^= 1 << k - 1
, A[ah[i][j]] ^= 1 << k - 1, ++cnt;
}
}
pair<int, int> begin = getMin(); dfs(begin.first, begin.second);
}
return 0;
}