zoukankan      html  css  js  c++  java
  • 数独

    链接

    优化:

    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
  • 相关阅读:
    HDOJ 4747 Mex
    HDU 1203 I NEED A OFFER!
    HDU 2616 Kill the monster
    HDU 3496 Watch The Movie
    Codeforces 347A A. Difference Row
    Codeforces 347B B. Fixed Points
    Codeforces 372B B. Hungry Sequence
    HDU 1476 Sudoku Killer
    HDU 1987 How many ways
    HDU 2564 词组缩写
  • 原文地址:https://www.cnblogs.com/xcfxcf/p/13605068.html
Copyright © 2011-2022 走看看