標籤:acm c 演算法
Sudoku
Time Limit: 1000MS |
|
Memory Limit: 65536K |
Total Submissions: 8152 |
|
Accepted: 2862 |
Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,
. |
2 |
7 |
3 |
8 |
. |
. |
1 |
. |
. |
1 |
. |
. |
. |
6 |
7 |
3 |
5 |
. |
. |
. |
. |
. |
. |
. |
2 |
9 |
3 |
. |
5 |
6 |
9 |
2 |
. |
8 |
. |
. |
. |
. |
. |
. |
. |
. |
. |
. |
. |
6 |
. |
1 |
7 |
4 |
5 |
. |
3 |
6 |
4 |
. |
. |
. |
. |
. |
. |
. |
9 |
5 |
1 |
8 |
. |
. |
. |
7 |
. |
. |
8 |
. |
. |
6 |
5 |
3 |
4 |
. |
Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns. Input The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”. Output For each test case, print a line representing the completed Sudoku puzzle. Sample Input .2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.end Sample Output 527389416819426735436751829375692184194538267268174593643217958951843672782965341416837529982465371735129468571298643293746185864351297647913852359682714128574936 Source Stanford Local 2006 |
題意:
就是經典的數獨問題。
思路:
搜尋。但是得藉助Dancing Links加速。關鍵就在於怎樣把數獨問題抽象成一個精確覆蓋問題了。
我們首先考慮數獨的遊戲規則。
1.每個格子都必須填一個數字。
2.每一行1-9這幾個數字都必須出現一次。
3.每一列1-9這幾個數字都必須出現一次。
4.每一宮格1-9這幾個數字都必須出現一次。
我們知道Dancing Links的精確覆蓋智能處理0,1的序列覆蓋每一列為一個約束條件。那麼我們就必須把上述約束轉換成0,1矩陣。
對於1。我們用第(i-1)*9+j列為1表示i行j列的已經填數。一共佔用81列。
對於2.我們用81+(i-1)*9+v列表示第i行已經有v這個值。一共佔用81列。
對於3.我們用162+(j-1)*9+v列表示第j列已經有v這個值。一共佔用81列。
對於3.我們用243+(3*((i-1)/3)+(j+2)/3-1)+v列表示第3*((i-1)/3)+(j+2)/3宮格已經有v這個值。一共佔用81列。
ps:i,j都從1開始。3*((i-1)/3)+(j+2)/3為通過i,j確定的宮格數。
這樣就會為每個宮格確定一個01序列約束。
然後建好矩陣後。套上精確覆蓋模板後就ok了。
詳細見代碼:
#include<iostream>#include<stdio.h>#include<string.h>using namespace std;const int INF=0x3f3f3f3f;const int maxn=3645;//每個格子可能有9個取值。所以最多有81*9行。然後243列。int U[maxn],D[maxn],L[maxn],R[maxn],C[maxn],row[maxn];//上下左右指標。c[i]結點i對應的列。row[i]結點i對應的行號。int S[350],H[800],ans[100];//S[i]為i列1的個數。H[i]為i行的尾指標。int n,m,cnt,deep;struct node{ int x,y,v;} st[maxn];char maze[150],path[150];void init(){ int i; for(i=1;i<=800;i++) H[i]=-1; for(i=0;i<=324;i++) { S[i]=0; L[i+1]=i; R[i]=i+1; U[i]=D[i]=i; } R[324]=deep=0; cnt=325;}void Insert(int r,int c){ //頭插法建鏈表 U[cnt]=c,D[cnt]=D[c];//確定新增結點上下指標資訊 U[D[c]]=cnt,D[c]=cnt;//恢複鏈表資訊 if(H[r]==-1) //確定左右指標資訊 H[r]=L[cnt]=R[cnt]=cnt;//加入頭 else { L[cnt]=H[r],R[cnt]=R[H[r]];//頭插法 L[R[H[r]]]=cnt,R[H[r]]=cnt; } S[c]++;//更新附加資訊 row[cnt]=r; C[cnt++]=c;}void Remove(int c)//移除c列。{ int i,j; R[L[c]]=R[c],L[R[c]]=L[c]; for(i=D[c];i!=c;i=D[i]) for(j=R[i];j!=i;j=R[j]) D[U[j]]=D[j],U[D[j]]=U[j],S[C[j]]--;}void Resume(int c)//還原c列。{ int i,j; R[L[c]]=L[R[c]]=c; for(i=D[c];i!=c;i=D[i]) for(j=R[i];j!=i;j=R[j]) D[U[j]]=U[D[j]]=j,S[C[j]]++;}bool dfs(){ if(R[0]==0) return true; int i,j,c,miv=INF; for(i=R[0];i;i=R[i]) if(S[i]<miv) miv=S[i],c=i; Remove(c);//處理第c列 for(i=D[c];i!=c;i=D[i]) { for(j=R[i];j!=i;j=R[j]) Remove(C[j]); ans[deep++]=row[i]; if(dfs()) return true; for(j=L[i];j!=i;j=L[j]) Resume(C[j]); deep--; } Resume(c); return false;}int main(){ int i,j,v,r,p; while(gets(maze)) { if(maze[0]=='e') break; init(); r=1; for(i=1;i<=9;i++)//每行為一個格子的一種選擇。 { for(j=1;j<=9;j++) { if(maze[(i-1)*9+j-1]=='.') { for(v=1;v<=9;v++) { Insert(r,(i-1)*9+j); Insert(r,81+(i-1)*9+v); Insert(r,162+(j-1)*9+v); Insert(r,243+(((i-1)/3)*3+(j+2)/3-1)*9+v); st[r].x=i,st[r].y=j,st[r].v=v; r++; } } else { v=maze[(i-1)*9+j-1]-'0'; Insert(r,(i-1)*9+j); Insert(r,81+(i-1)*9+v); Insert(r,162+(j-1)*9+v); Insert(r,243+(((i-1)/3)*3+(j+2)/3-1)*9+v); st[r].x=i,st[r].y=j,st[r].v=v; r++; } } } dfs(); for(i=0;i<deep;i++) { p=ans[i]; path[(st[p].x-1)*9+st[p].y-1]='0'+st[p].v; } path[deep]=0; printf("%s\n",path); } return 0;}