数独

链接

优化:

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;
                }
            }
        }
    }
View Code

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;
}
View Code
原文地址:https://www.cnblogs.com/xcfxcf/p/13605068.html