我目前找到的最快的數獨求解程式
在瓶哥SuDoKu_DLX_9*9 程式基礎上新增了檔案操作。
測試檔案來自
http://staffhome.ecm.uwa.edu.au/~00013890/sudokumin.php
用vc2010的cl sudokudlx.cpp /MD -O2編譯,執行總時間2.7秒,絕大部分單個問題都不足1毫秒。瓶哥說只比他的dfs9*9 程式快4倍是不準確的。他的測試用例過少,我用dfs解第一個問題就花了10秒。
#include <cstdio> #include <cstring> #include <ctime> const int XSIZE = 3; const int SIZE = XSIZE * XSIZE; const int MAX_C = SIZE * SIZE * 4; //最大列 const int MAX_R = SIZE * SIZE * SIZE; //最大行 const int MAX_SUDOKU = SIZE * SIZE; //數獨矩陣大小 const int MAX_LINK = MAX_C * MAX_R; //連結串列最大範圍 int L[MAX_LINK],R[MAX_LINK],U[MAX_LINK],D[MAX_LINK]; //抽象連結串列 int C[MAX_LINK],O[MAX_LINK],S[MAX_C],H[MAX_R]; //C&O代表列&行,S每一列的節點數,H每一行的第一個節點 int NodeNumber,RecordNumber; //用來指向節點 int state[MAX_SUDOKU],ans[MAX_SUDOKU],record[MAX_SUDOKU]; //////////////////////Dancing Links模版////////////////////// void init(void); //Dancing Links的抽象連結串列初始化 void insert(int,int); //在連結串列的一個位置中新增標記 void remove(int); //刪除一列,同時刪除這一列中的行 void resume(int); //恢復一列,同時恢復這一列中的行 //////////////////////Dancing Links模版////////////////////// bool input(void) { char buffer[SIZE+1][SIZE+1];//留一個空間 if(scanf("%s",buffer[0])==EOF) return false; for(int i=1;i<SIZE;i++) scanf("%s",buffer[i]); memset(state,0,sizeof(state)); for(int i=0;i<SIZE;i++) for(int j=0;j<SIZE;j++) { if(buffer[i][j]!='0') state[i*SIZE+j]=buffer[i][j]-'0'; } return true; } char buffer2[SIZE*SIZE+3];//留一個空間給換行符 bool input2(FILE* f) { if(NULL== fgets(buffer2,SIZE*SIZE+2,f)) return false; memset(state,0,sizeof(state)); for(int i=0;i<SIZE;i++) for(int j=0;j<SIZE;j++) { //if(buffer[i][j]!='0') state[i*SIZE+j]=buffer2[i*SIZE+j]-'0'; } return true; } void add(int i,int j,int k) { int row=i*MAX_SUDOKU+j*SIZE+k; insert(row,i*SIZE+j+1);//注意 insert(row,i*SIZE+k+MAX_SUDOKU); insert(row,j*SIZE+MAX_SUDOKU*2+k); insert(row,(i/XSIZE*XSIZE +j/XSIZE)*SIZE+MAX_SUDOKU*3+k); } void build(void) { int pos,row; for(int i=0;i<SIZE;i++) for(int j=0;j<SIZE;j++) { pos=i*SIZE+j; if(state[pos]!=0) { add(i,j,state[pos]); } else if(state[pos]==0) { for(int k=1;k<=SIZE;k++) { add(i,j,k); } } } } bool dfs(int k) { if(!R[0]) { RecordNumber=k; return true; } int count=~(1<<31),c; for(int i=R[0];i;i=R[i]) { if(S[i]<count) { count=S[i]; c=i; if(count==1) break; } } remove(c); for(int i=D[c];i!=c;i=D[i]) { for(int j=R[i];j!=i;j=R[j]) { remove(C[j]); } record[k]=O[i]; if(dfs(k+1)) return true; for(int j=L[i];j!=i;j=L[j]) { resume(C[j]); } } resume(c); return false; } void output(void) { for(int i=0;i<RecordNumber;i++) { ans[(record[i]-1)/SIZE]=(record[i]-1)%SIZE+1; } for(int i=0;i<SIZE;i++) { for(int j=0;j<SIZE;j++) printf("%-2d",ans[i*SIZE+j]); printf("\n"); } } void output2(FILE* f ) { for(int i=0;i<RecordNumber;i++) { ans[(record[i]-1)/SIZE]=(record[i]-1)%SIZE+1; } for(int i=0;i<SIZE;i++) { for(int j=0;j<SIZE;j++) fprintf(f,"%-2d",ans[i*SIZE+j]); fprintf(f,"\n"); } } int main() { FILE *fp=fopen("d:\\sudoku17.txt","rt"); FILE *fo=fopen("d:\\sudoku17res.txt","wt"); while(input2(fp)) { time_t start=clock(); init(); build(); dfs(0); fprintf(fo,"%s\n",buffer2); output2(fo); fprintf(fo,"Time:%ldMs\n",clock()-start); } fclose(fp); fclose(fo); return 0; } //////////////////////Dancing Links模版////////////////////// void init(void) { for(int i=0;i<=MAX_C;i++) { L[i]=i-1; R[i]=i+1; U[i]=i; D[i]=i; C[i]=i; O[i]=0; } L[0]=MAX_C; R[MAX_C]=0; NodeNumber=MAX_C+1; memset(S,0,sizeof(S)); memset(H,0,sizeof(H)); } void insert(int i,int j) { if(H[i]) { L[NodeNumber]=L[H[i]]; R[NodeNumber]=H[i]; L[R[NodeNumber]]=NodeNumber; R[L[NodeNumber]]=NodeNumber; } else { L[NodeNumber]=NodeNumber; R[NodeNumber]=NodeNumber; H[i]=NodeNumber; } U[NodeNumber]=U[j]; D[NodeNumber]=j; U[D[NodeNumber]]=NodeNumber; D[U[NodeNumber]]=NodeNumber; C[NodeNumber]=j; O[NodeNumber]=i; S[j]++; NodeNumber++; } void remove(int c) { L[R[c]]=L[c]; R[L[c]]=R[c]; for(int i=D[c];i!=c;i=D[i]) { for(int j=R[i];j!=i;j=R[j]) { U[D[j]]=U[j]; D[U[j]]=D[j]; S[C[j]]--; } } } void resume(int c) { for(int i=U[c];i!=c;i=U[i]) { for(int j=L[i];j!=i;j=L[j]) { U[D[j]]=j; D[U[j]]=j; S[C[j]]++; } } L[R[c]]=c; R[L[c]]=c; } /* 070680050 000000001 409507000 560000340 000000000 034000017 000703804 300000000 090015030 */
相關文章
- 另一個數獨求解c++程式C++
- 又一個數獨求解c++程式C++
- 改進版的python求解數獨Python
- 國內目前最快的dns 2022解析最快的dnsDNS
- 僅50行Python程式碼!數獨求解!4秒!Python
- 同樣演算法的Python和C求解數獨程式速度比較演算法Python
- [LeetCode] Sudoku Solver 求解數獨LeetCode
- 可能是目前最快的struct複製庫Struct
- Vert.x的介紹!這是目前最快的Java框架Java框架
- JAVA 2目前的3個獨立的版本Java
- 一個解數獨的程式
- 零程式設計經驗的我是如何找到工作的程式設計
- 目前做什麼賺錢最快?專案推薦!
- 梯度下降法中導數的求解梯度
- uniapp js 數獨小遊戲 寫死的簡單數獨 數獨 3.0APPJS遊戲
- Github clone程式碼最快的方式Github
- 讓我們一起啃演算法----有效的數獨演算法
- 最快的程式碼,是不執行的程式碼
- 我是如何在Stack Overflow找到工作的
- 我是如何在自學程式設計9個月後找到工作的程式設計
- 從事程式設計後,讓我最快樂的十件事程式設計
- 如何找到埠的程式號
- 【演算法詳解】求解數值的整數次方演算法
- 羅塞塔網站上的c++解數獨程式網站C++
- 據說用概率去解數獨的c++程式C++
- 解析最快的dns 最快最穩定的dnsDNS
- 求區間不同數的個數【樹狀陣列求解】陣列
- 我能找到工作嗎?
- 本人已找到遠端工作 提了離職 目前公司需要一個程式設計師維護程式碼程式設計師
- 目前最好的雲遊戲,我玩了幾天《雲·原神》,真香!遊戲
- 我眼裡的HTML5好書,截至目前出版HTML
- 找到一個數最接近的比它大的2的n次冪的程式碼分析
- 拉丁方的衍生遊戲“數獨”遊戲
- leetcode:有效的數獨LeetCode
- [譯] 我是如何找到谷歌 UX 設計工作的谷歌UX
- 我是如何找到 Express 應用延遲原因的Express
- 目前美國已掌握數TB的維基解密資料解密
- 國內DNS最快的伺服器 解析最快的dnsDNS伺服器