(nice!!!)LeetCode 37. 解数独(深度优先搜索dfs、位运算bitset)

37. 解数独

在这里插入图片描述
在这里插入图片描述
思路:建议直接看大佬的题解,用三个数组,来保存整个board的状态。很巧妙的用到了bitset来记录数字被选定的状态,进行了状态压缩。
题解还从最小的可选状态(i,j)出发。

需要注意的是row、col、ceil数组的构建,卡住我一个多小时,人都麻了。

class Solution {
public:
    vector<bitset<9>> row,col;
    vector<vector<bitset<9>>> ceil;

    bitset<9> getNum(int i,int j){
        return ~(row[i]|col[j]|ceil[i/3][j/3]);
    }

    vector<int> getPosition(vector<vector<char>>& board){
        vector<int> v;
        int minn=10;
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                if(board[i][j]!='.') continue;
                auto tmp=getNum(i,j);
                if(tmp.count()<minn){
                    minn=tmp.count();
                    v={i,j};
                }
            }
        }
        if (v.empty()) return {}; // 确保有有效值返回
        return v;
    }

    bool dfs(vector<vector<char>>& board,int ct){
        if(ct==0) return true;
        auto id=getPosition(board);
        if(id.empty()) return false;
        int x=id[0],y=id[1];
        auto tmp=getNum(x,y);
        for(int i=0;i<tmp.size();i++){
            if(tmp[i]==1){
                board[x][y]=i+'1';
                row[x][i]=1;
                col[y][i]=1;
                ceil[x/3][y/3][i]=1;
                if(dfs(board,ct-1)) return true;
                board[x][y]='.';
                row[x][i]=0;
                col[y][i]=0;
                ceil[x/3][y/3][i]=0;
            }
        }
        return false;
    }

    void solveSudoku(vector<vector<char>>& board) {
        row = vector<bitset<9>>(9, bitset<9>());
        col = vector<bitset<9>>(9, bitset<9>());
        ceil = vector<vector<bitset<9>>>(3, vector<bitset<9>>(3, bitset<9>()));
        //进行预处理
        int ct=0;
        for(int i=0;i<board.size();i++){
            for(int j=0;j<board[0].size();j++){
                if(board[i][j]=='.'){
                    ct++;
                }else{
                    int tmp=board[i][j]-'1';
                    row[i][tmp]=1;
                    col[j][tmp]=1;
                    ceil[i/3][j/3][tmp]=1;
                }
                
            }
        }
        cout<<ct;
        dfs(board,ct);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值