https://blog.csdn.net/xiaozhuaixifu/article/details/12253507
給定一個不完整9*9數獨,
未填部分用0表示,
恢復數獨,並打印
在讀入的時候,
我們開幾個數組,
sudoku[9][9],相當於這張數獨地圖,上面記錄值
checkrow[9][10],第i行,是否出現過數v,1<=v<=9
checkcol[9][10],第j列,是否出現過數v,1<=v<=9
square[9][10],第k塊,是否出現過數v,1<=v<=9
塊的定義,
即圖片中漢字數字順序,對應0-8塊,
k=i/3*3+j/3可表示。
//圖片來源於網絡http://blog.sina.com.cn/s/blog_4e92a29f010171dc.html
我們從(0,0)開始dfs,
如果行末,就dfs下一行行首;
如果非行末,就dfs本行下一列,
如果到(9,0)了,說明前面均無衝突。
然後就是dfs經典三段論。
①試數,對應修改
②向更深層次搜索
③(如果能到這裏,說明②失敗)將①還原
博主這篇文章真的是好評,
代碼風格也很好,剪枝也減的恰到好處,
搜到一個可行解,isdone就返回,
雖然沒加一句註釋,但通俗易懂。
QAQ數獨的確是一種經典題,還是要多練爲妙
全oj大概有那麼五六個數獨題吧,
16*16的,靶型數獨的,以後再補吧
講道理,貼代碼裏面的i,個人覺得,好吃藕
#include <iostream> #include <algorithm> #include <cstring> #include <string.h> #include <cstdio> #include <cmath> #include <set> #include <vector> #include <stack> #include <queue> #include <map> const double INF=0x3f3f3f3f; const int maxn=1e5+10; const int mod=1e9+7; const int MOD=998244353; const double eps=1e-7; typedef long long ll; #define vi vector<int> #define si set<int> #define pii pair<int,int> #define pi acos(-1.0) #define pb push_back #define mp make_pair #define lowbit(x) (x&(-x)) #define sci(x) scanf("%d",&(x)) #define scll(x) scanf("%lld",&(x)) #define sclf(x) scanf("%lf",&(x)) #define pri(x) printf("%d",(x)) #define rep(i,j,k) for(int i=j;i<=k;++i) #define per(i,j,k) for(int i=j;i>=k;--i) #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; char tmp[9]; int sudoku[9][9]; bool square[9][10];//第i個3*3塊,數j是否已經出現 bool checkrow[9][10];//第i行,數j是否已經出現 bool checkcol[9][10];//第i列,數j是否已經出現 bool isdone;//是否搜到一個可行解 void init() { mem(checkrow,0); mem(checkcol,0); mem(square,0); isdone=0; } void dfs(int i,int j)//當前判sodaku[i][j]是否合法 { if(i==9) { isdone=1;//搜到一個答案 rep(i,0,8) { rep(j,0,8) { printf("%d",sudoku[i][j]); } puts(""); } return; } if(isdone)return;//已經搜到一個可行解了,把剩下的剪枝 if(sudoku[i][j])//這裏已經置入一個數了 { if(j==8)dfs(i+1,0);//搜到行末了,新開一行 else dfs(i,j+1); } else { rep(v,1,9) { int k=i/3*3+j/3;//第k塊 if(!checkrow[i][v]&&!checkcol[j][v]&&!square[k][v])//o(1)查重的操作 { //先試試,v能不能行 sudoku[i][j]=v; checkrow[i][v]=1; checkcol[j][v]=1; square[k][v]=1; //向後續搜索 if(j==8)dfs(i+1,0); else dfs(i,j+1); //能運行到這句,說明不行,改回來 sudoku[i][j]=0; checkrow[i][v]=0; checkcol[j][v]=0; square[k][v]=0; } } } } int main() { int t; sci(t); while(t--) { init(); rep(i,0,8) { scanf("%s",tmp); rep(j,0,8) { int v=tmp[j]-'0'; sudoku[i][j]=v; if(v) { int k=i/3*3+j/3;//第k塊 checkrow[i][v]=1;//i行出現過v checkcol[j][v]=1;//j列出現過v square[k][v]=1;//k塊出現過v } } } dfs(0,0); } return 0; }