9 * 9的格子,一个格子九种填法,暴搜肯定TLE
考虑优化
1、选择优化,由于肯定有解,我们先搜索可选条件少的点
2、其次考虑如何快速得到我们选择的点还可以选哪几个,我们知道的限制有行上、列上、单个3 * 3九宫格内,我们能选的就是这几个的交集,为了快速得到,就需要用位运算优化
我们建立ROW数组存储第i列可选的数,COL存储第i列可选的数,cell存储第i,j个九格宫可以存储的数,用二进制存储状态
比如第1行,2、7、3、8、1都不可以选择了,那么这一行的状态用二进制表示就是100111001,0代表还未使用,1表示已经使用
那么对于第i,j个点,我们可以选的二进制状态就是 r[i] & c[j] & cell[i][j];
为了快速得到某个二进制数中的1,就用到了lowbit函数,求一个二进制最低位的1,因为我们得到这个1以后也是一个二进制数,为了快速得到他代表数字几,我们要需要打表map记录每种二进制代表哪个数字
我们说了要优先选择可选少的,那么为了快速得到某个点的可选数,我们还需要打表ones数组,记录每个二进制中有几个1
#include
#include
#include
using namespace std;
const int N = 9;
int ones[1 << N], map[1 << N];
int r[N], c[N], cell[3][3];
string str;
inline int lowbit(int x) {return x & -x;}//lowbit函数求二进制最低位1
inline void init() {//初始化
for(int i = 0;i < N;i++) r[i] = c[i] = (1 << N) - 1;
//(1 << N) - 1 = (二进制)111111111
//表示刚开始,每个数都可以选
for(int i = 0;i < 3;i++)
for(int j = 0;j < 3;j++)
cell[i][j] = (1 << N) - 1;//刚开始每个九格宫内9个数都可以选
}
inline int get(int x, int y) {return r[x] & c[y] & cell[x / 3][y / 3];}//得到x,y这个点可选的状态
bool dfs(int cnt){
if(!cnt) return true;
int minn = 10, x = 0, y = 0;
for(int i = 0;i < N;i++){//找到可选最少的那个点
for(int j = 0;j < N;j++){
if(str[i * 9 + j] == '.'){
int t = ones[get(i, j)];
if(t < minn){
minn = t, x = i, y = j;
}
}
}
}
// cout << x << " " << y << endl;
// return false;
for(int i = get(x, y);i;i -= lowbit(i)){//枚举这个点上可选的数
int t = map[lowbit(i)];
r[x] -= 1 << t;
c[y] -= 1 << t;
cell[x / 3][y / 3] -= 1 << t;
str[x * 9 + y] = t + '1';
if(dfs(cnt - 1)) return true;
r[x] += 1 << t;//回溯
c[y] += 1 << t;//回溯
cell[x / 3][y / 3] += 1 << t;//回溯
str[x * 9 + y] = '.';//回溯
}
return false;
}
int main(){
for(int i = 0;i < N;i++) map[1 << i] = i;//打表
for(int i = 0;i < 1 << N;i++) {
int s = 0;
for(int j = 0;j < N;j++) {
if(i >> j & 1) s++;
}
ones[i] = s;//打表
}
while(cin >> str && str[0] != 'e') {
init();//先初始化
int cnt = 0;//记录有几个空需要填
for(int i = 0, k = 0;i < N;i++) {
for(int j = 0;j < N;j++, k++) {
if(str[k] != '.'){//如果不是空格,就是有数,我们把行、列、九格宫状态更新一下
r[i] -= 1 << (str[k] - '1');
c[j] -= 1 << (str[k] - '1');
cell[i / 3][j / 3] -= 1 << (str[k] - '1');
}
else cnt++;
}
}
dfs(cnt);
cout << str << endl;
}
return 0;
}