优化:
1 唯一确定的数字
2 空的格子少的
int minv = 10,minx = -1,miny = -1; for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ if(s[i * 9 + j] == '.'){ int c = ones[get(i,j)]; if(c < minv){ minv = c; minx = i;miny = j; } } } }
r,c,分别记录行和列的数字
cel记录每个九宫格里面的数字
最初都假设为1,表示可选数字,
i | 1 << i | 1 << i - 1 |
0 | 1 | 0 |
1 | 10 | 1 |
2 | 100 | 11 |
3 | 1000 | 111 |
4 | 10000 | 1111 |
5 | 100000 | 11111 |
6 | 1000000 | 111111 |
7 | 10000000 | 1111111 |
8 | 100000000 | 11111111 |
.... | ||
000000001表示可填1
000000101表示3 和 1可填
如果字符串s中出现了数字,那么当前行列九宫格里面的这个数字变为0,
mp来映射 mp[1 << i] = i;
ones[i]表示i里面有几个1
#include <bits/stdc++.h> using namespace std; const int n = 9; const int maxn = 1 << n; int r[n],c[n],cel[n/3][n/3];//行 列 九宫格 char s[110]; int ones[maxn];//每个数字里面包含的1的个数,1等价 1,2等价 10,3等价11 int mp[maxn];//数字对应关系 inline int lowbit(int x){ return x & -x; } inline int get(int x,int y){ return r[x] & c[y] & cel[x/3][y/3]; } int dfs(int cnt,char s[]){ if(!cnt) return 1;//数字都填好了 int minv = 10,minx = -1,miny = -1; for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ if(s[i * 9 + j] == '.'){ int c = ones[get(i,j)]; if(c < minv){ minv = c; minx = i;miny = j; } } } } if(!minv) return 0;//又要修改的点,但是为0 int trynums = get(minx,miny); while(trynums){ int trynum = mp[lowbit(trynums)]; r[minx] -= 1 << trynum; c[miny] -= 1 << trynum; cel[minx/3][miny/3] -= 1 << trynum; s[minx * 9 + miny] = '1' + trynum; if(dfs(cnt - 1,s)) return 1; r[minx] += 1 << trynum; c[miny] += 1 << trynum; cel[minx/3][miny/3] += 1 << trynum; s[minx * 9 + miny] = '.' ; trynums -= lowbit(trynums); } return 0; } void init(){ for(int i = 0; i < n; i++){ r[i] = c[i] = (1 << n) - 1;//每行每列都先标记为1 mp[1 << i] = i; } //每个九宫格的标记 for(int i = 0; i < n / 3; i++) { for (int j = 0; j < n / 3; j++){ cel[ i ][ j ] = (1 << n) - 1; } } } int main(){ //freopen("in","r",stdin); ios::sync_with_stdio(0); //每个数字里面1的个数 for(int i = 0; i < 1 << n; i++) for(int j = i; j;j -= lowbit(j)) ones[i]++; while(cin >> s && s[0] != 'e'){ //cout << s << endl; init(); int cnt = 0; for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ if(s[i * 9 + j] != '.'){//表示已经有数字了 int num = 1 << (s[i * 9 + j] - '1'); r[i] -= num;c[j] -= num; cel[i / 3][j / 3] -= num; }else cnt++; } } dfs(cnt,s); cout << s << endl; } return 0; }