AcWing 166. 数独

    科技2025-06-03  38

    题意:

    完成数独

    思路:

    看到题目,这肯定是搜索,但是试了一发普通的直接就超时了,肯定要加一些剪枝和优化,首先是位运算优化可以将每一行,每一列,每一个九宫格,都利用一个九位二进制数保存,当前还有哪些数字可以填写,再一个我们肯定是从限制性最高的那个点开始填的,其实每次都是填限制最多的那个数, 涉及到一个lowbit函数:当前得需要用lowbit运算取出当前可以能填的数字.

    AC代码:

    #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e6+10; char mp[10][10];//二维和一维存放 int c[10],r[10],g[10];//行与列 int cnt[1100],num[1100]; int k,tot; int lowbit(int x) { return x&(-x); } int get(int x,int y) { return ((x/3)*3)+(y/3); } void fun(int x,int y,int z) { r[x]^=1<<z; c[y]^=1<<z; g[get(x,y)]^=1<<z; } int dfs(int now) { if(now == 0) return 1; int tmp = 10,x,y; for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { if(mp[i][j]!='.') continue; int val = r[i] & c[j] & g[get(i,j)]; if(!val) return 0; if(cnt[val]<tmp) { tmp = cnt[val]; x = i,y = j; } } } int val = r[x] & c[y] & g[get(x,y)]; for(;val;val-=lowbit(val)) { int z = num[lowbit(val)]; mp[x][y] = z+'1'; fun(x,y,z); if(dfs(now-1)) return 1; fun(x,y,z); mp[x][y] = '.'; } return 0; } int main() { for(int i=0;i<1<<9;i++) {//预处理初始能放的数有多少个 for(int j=i;j;j-=lowbit(j)) { cnt[i]++; } } for(int i=0;i<9;i++) num[1<<i] = i; char s[100]; while(scanf("%s",s)&&s[0]!='e') { for(int i=0;i<9;i++) c[i] = r[i] = g[i] = (1<<9)-1; for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { mp[i][j] = s[i*9+j]; } } tot=0; for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { if(mp[i][j]!='.') { fun(i,j,mp[i][j]-'1'); } else { tot++; } } } dfs(tot); for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { s[i*9+j] = mp[i][j]; } } puts(s); } }
    Processed: 0.011, SQL: 8