第一篇博客送给数独吧~
题目大意就是填数独(如同废话)
没有进行搜索顺序剪枝,532ms过的...
分析:
用二进制来存储可以填的数,用a[i]表示i行可以填的数,b[i]表示i列可以填的数,c[i][j]表示第i行j列的九宫格可以填的数。
当准备填一个数的时候,把它所在的行、列、九宫格做“与”运算,用lowbit()得到它能填的所有数。
接下来就是每次递归失败后把a, b, c和num数组复原,用到了memcpy函数(不用memcpy就是多写3行而已)
还有就是我的二进制操作很多没加括号,建议大家不要学我...
最后就是多组数据记得清空。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int T, num[9][9], a[9], b[9], c[3][3], m[257];
char s;
bool dfs(int x, int y) {
if(x == 9) {
for(int i = 0; i < 9; i++, printf("\n"))
for(int j = 0; j < 9; j++)
printf("%d", num[i][j]);
return true;
}
if(num[x][y]) return dfs(y==8?x+1:x, y==8?0:y+1);
int ss = a[x] & b[y] & c[x/3][y/3], aa[9], bb[9], cc[3][3], t;
memcpy(aa, a, sizeof a);
memcpy(bb, b, sizeof b);
memcpy(cc, c, sizeof c);
while(t = m[ss & -ss]) {
num[x][y] = t;
if(a[x] & 1<<t-1)
a[x] ^= 1<<t-1;
if(b[y] & 1<<t-1)
b[y] ^= 1<<t-1;
if(c[x/3][y/3] & 1<<t-1)
c[x/3][y/3] ^= 1<<t-1;
if(dfs(y==8?x+1:x, y==8?0:y+1)) return true;
num[x][y] = 0;
memcpy(a, aa, sizeof a);
memcpy(b, bb, sizeof b);
memcpy(c, cc, sizeof c);
ss ^= ss & -ss;
}
return false;
}
int main() {
for(int i = 1; i <= 9; i++)
m[1<<i-1] = i;
scanf("%d", &T);
while(T--) {
for(int i = 0; i < 9; i++)
a[i] = b[i] = (1<<9)-1;
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
c[i][j] = (1<<9)-1;
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++) {
cin>>s;
int t = s-'0';
num[i][j] = t;
if(t) {
if(a[i] & 1<<t-1)
a[i] ^= 1<<t-1;
if(b[j] & 1<<t-1)
b[j] ^= 1<<t-1;
if(c[i/3][j/3] & 1<<t-1)
c[i/3][j/3] ^= 1<<t-1;
}
}
dfs(0, 0);
}
return 0;
}