数独_DFS剪枝,状态压缩,lowbit树

166. 数独

数独是一种传统益智游戏,你需要把一个 9×9 的数独补充完整,使得图中每行、每列、每个 3×3 的九宫格内数字 19 均恰好出现一次。

请编写一个程序填写数独。

输入格式

输入包含多组测试用例。

每个测试用例占一行,包含 81 个字符,代表数独的 81 个格内数据(顺序总体由上到下,同行由左到右)。

每个字符都是一个数字(19)或一个 .(表示尚未填充)。

您可以假设输入中的每个谜题都只有一个解决方案。

文件结尾处为包含单词 end 的单行,表示输入结束。

输出格式

每个测试用例,输出一行数据,代表填充完全后的数独。

输入样例:

4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
end

输出样例:

417369825632158947958724316825437169791586432346912758289643571573291684164875293
416837529982465371735129468571298643293746185864351297647913852359682714128574936

代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 9, M = 1 << N;
int row[N], col[N], cell[3][3];
int ones[M], m[M];
string str;
int flag;
void init(){
    flag = 0;
    for(int i = 0; i < N; i++){
        row[i] = (1 << N) - 1;
        col[i] = (1 << N) - 1;
        cell[i / 3][i % 3] = (1 << N) - 1;
    } 
    
}
void draw(int x, int y, int t, int is_set){
    int a = 1 << t;
    
    if(is_set){
        str[x * N + y] = t + '1';
        row[x] -= a;
        col[y] -= a;
        cell[x / 3][y / 3] -= a;
    }else{
        str[x * N + y] = '.';
        row[x] += a;
        col[y] += a;
        cell[x / 3][y / 3] += a;
    }
}
int get(int x, int y){
    return row[x] & col[y] & cell[x / 3][y / 3];
}
int lowbit(int x){
    return x & -x;
}
void dfs(int cnt){
    if(!cnt){
        cout << str << endl;
        flag = 1;
        return ;
    }
    if(flag)return;
    int MIN = 10;
    int x, y;
    for(int i = 0; i < N; i++){
        for(int j = 0; j < N; j++){
            if(str[i * N + j] == '.'){
                int state = get(i,j);
                int sum = ones[state];
                
                if(sum < MIN){
                    MIN = sum;
                    x = i, y = j;
                }
            }
            
        }
    }
    //printf("x = %d  y = %d\n",x,y);
    int state = get(x,y);
    for(int i = state; i; i -= lowbit(i)){
        int t = m[lowbit(i)];
        draw(x,y,t,1);
        dfs(cnt - 1);
        draw(x,y,t,0);
        
    }
}
int main(){
    for(int i = 0; i < N; i++)  m[1 << i] = i;
    for(int i = 0; i < M; i++)
        for(int j = 0; j < N; j++)
            ones[i] += (i >> j) & 1;
    
    
    while(cin >> str, str[0] != 'e'){
        init();
        int cnt = 0;
        for(int i = 0; i < N; i++){
            for(int j = 0; j < N; j++){
                char c = str[i * N + j];
                if(c != '.'){
                    draw(i,j,c - '1',1);
                }else cnt++;
            }
            //cout << endl;
        }
        flag = 0;
        dfs(cnt);
    }
    return 0;
}

  

 
posted @ 2022-02-25 15:47  荣荣荣荣荣荣  阅读(61)  评论(0)    收藏  举报