AcWing 166.数独
这道题一看起来就很麻烦,但是可以用bitset进行优化
暴力搜索就是了
代码如下:
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3, "Ofast", "inline")
#include<cstdio>
#include<cstring>
#include<bitset>
using namespace std;
const int maxn = 10;
bitset<maxn> r[maxn], c[maxn], b[maxn];
int N, G[maxn][maxn];
inline void init(void){
memset(G, 0, sizeof(G));
N = 0;
for(int i = 0; i < maxn; i++){
r[i].set(); c[i].set(); b[i].set();
}
}
bool dfs(int n){
if(n == N) return true;
//寻找最少的
int minv = 10, id = 100;
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++)
if(G[i][j] == 0){
int num = (r[i] & c[j] & b[(j / 3) + (i / 3) * 3]).count();
if(num == 0) return false;
if(num < minv){minv = num; id = i * 9 + j;}
}
int rr = id / 9, cc = id % 9; bitset<maxn> x = r[rr] & c[cc] & b[(cc / 3) + (rr/ 3) * 3];
for(int i = 1; i <= 9; i++){
if(x.test(i)){
r[rr].reset(i); c[cc].reset(i); b[(cc / 3) + (rr/ 3) * 3].reset(i); G[rr][cc] = i;
if(dfs(n + 1)) return true;
r[rr].set(i); c[cc].set(i); b[(cc / 3) + (rr/ 3) * 3].set(i); G[rr][cc] = 0;
}
}
return false;
}
inline void output(void){
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++){
printf("%d", G[i][j]);
}
putchar('\n');
}
int main(void)
{
char _c;
while(true){
if((_c = getchar()) =='e') break;
init();
for(int i = 0; i < 81; i++){
if(_c != '.'){
int rr = i / 9, cc = i % 9;
r[rr].reset(_c - '0'); c[cc].reset(_c - '0');
b[(cc / 3) + (rr/ 3) * 3].reset(_c - '0');
G[rr][cc] = _c - '0';
}
else N++;
_c = getchar();
}
dfs(0);
output();
}
return 0;
}
其中,对于在某一个位置填入数的时候r,c,b的变化可以写在函数里,使程序更加规整
而r[i]代表第i行,能填入的数是哪些,如果能填入则相应的二进制位为1
c代表行的,b代表块的