题目大意
给你一些数独题,让你填。
空位以 ‘.’ 表示,多组数据,以end结尾。
解
深度搜索,剪枝。
用二进制位压缩储存状态,用这个以判断当前位置可以填的数字。
代码
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int l[20], h[20], z[5][5], k[20][20], flag;
char c;
char getc(){
//输入
char lc = getchar();
while(( lc>'9' || lc<'0' ) && lc != '.' && lc != 'e') lc = getchar();
return lc;
}
void init(){
//输入
memset(l, 0, sizeof(l));
memset(h, 0, sizeof(h));
memset(z, 0, sizeof(z));
for(int i = 1; i <= 9; ++i){
for(int j = 1; j <= 9; ++j){
if(c != '.'){
k[i][j] = c-48;
l[j] += 1 << (c-48-1); //列,这个数的状态为1(填过)
h[i] += 1 << (c-48-1); //行,这个数的状态为1(填过)
z[(i+2)/3][(j+2)/3] += 1 << (c-48-1); //小矩阵,这个数的状态为1(填过)
}
else k[i][j] = 0;
c = getc();
}
}
}
void printt(){
//输出
for(int i = 1; i <= 9; ++i)
for(int j = 1; j <= 9; ++j)
printf("%d", k[i][j]);
printf("\n");
}
void dfs(int bh){
if(bh > 81){
//找到答案
flag = 1;
printt();
return;
}
int x = (bh+8) / 9, y = (bh-1) % 9 + 1; //当前点坐标
int jzx = (x+2) / 3, jzy = (y+2) / 3; //小矩阵是哪一个
if(k[x][y] != 0) dfs(bh + 1); //如果它本来就给出了这个数
else for(int i = 1; i <= 9; ++i){
//枚举
if((h[x] >> (i-1)) % 2 == 0) //行没出现
if((l[y] >> (i-1)) % 2 == 0) //列没出现
if((z[jzx][jzy] >> (i-1)) % 2 == 0){
//小矩阵没出现
h[x] += 1 << (i-1); //改变状态
l[y] += 1 << (i-1);
z[jzx][jzy] += 1 << (i-1);
k[x][y] = i; //记录答案
dfs(bh+1);
k[x][y] = 0;
if(flag == 1) return;
h[x] -= 1 << (i-1);
l[y] -= 1 << (i-1);
z[jzx][jzy] -= 1 << (i-1);
}
}
}
int main(){
c = getc();
while(c!='e'){
//多组数据
init();
flag = 0;
dfs(1);
}
}