题意:解数独
分析:
完整的数独有四个充要条件:
1.每个格子都有填数字
2.每列都有1~9中的每个数字
3.每行都有1~9中的每个数字
4.每个9宫格都有1~9中的每个数字
可以转化成精确覆盖问题。每行表示一个格子的一种填法,1~81列表示这个格子的位置,82~162列表示这是哪一行的什么数字,163~243列表示这是哪一列的什么数字,244~324列表示这是哪一个九宫格里的什么数字。每行都把四个1填入这四个区间里的对应位置。最后求出这个01矩阵的精确覆盖就是解。
对于已经确定的点 我们就直接建一行 对于没有确定的点我们就 建k行(k<=9),这样说如果在该行该列或者该3*3的矩阵中存在该数字 则对应的该数字所在的行就没有必要建立了
这样跑一次dlx精确覆盖就ok了
#include <iostream> #include <algorithm> #include <cstdio> #include <vector> #include <string.h> using namespace std; const int M=9*9*9*10*4; struct node{ int c,x,y,k; }; struct DLX { int n,sz; int S[9*9*5]; int row[M],col[M]; int L[M],R[M],U[M],D[M]; int ans[10][10]; int X[M],Y[M],Cnt[M]; void init(int n) { this->n=n; for(int i=0; i<=n; i++) { U[i]=i;D[i]=i; L[i]=i-1; R[i]=i+1; } R[n]=0;L[0]=n; sz=n+1; memset(S,0,sizeof(S)); } void addRow(int r,vector<node>columns) { int first=sz; for(int i=0; i<columns.size();i++) { int c=columns[i].c; X[sz]=columns[i].x; Y[sz]=columns[i].y; Cnt[sz]=columns[i].k; L[sz]=sz-1; R[sz]=sz+1; D[sz]=c; U[sz]=U[c]; D[U[c]]=sz;U[c]=sz; row[sz]=r;col[sz]=c; S[c]++;sz++; } R[sz-1]=first; L[first]=sz-1; } #define FOR(i,A,s) for(int i=A[s]; i!=s; i=A[i]) void remove(int c) { L[R[c]]=L[c]; R[L[c]]=R[c]; FOR(i,D,c) FOR(j,R,i) { U[D[j]]=U[j];D[U[j]]=D[j];--S[col[j]]; } } void restore(int c) { FOR(i,U,c) FOR(j,L,i) { ++S[col[j]];U[D[j]]=j;D[U[j]]=j; } L[R[c]]=c; R[L[c]]=c; } bool dfs(int d) { if(R[0]==0)return true; else { int num=R[0]; FOR(i,R,0) { if(S[i]==0) return false; if(S[num]>S[i]) { num=i; } } remove(num); FOR(i,D,num) { ans[X[i]][Y[i]]=Cnt[i]; FOR(j,R,i)remove(col[j]); if(dfs(i+1)) { return true; } FOR(j,L,i)restore(col[j]); } restore(num); return false; } } }Link; bool hasr[10][10],hasc[10][10],hasp[10][10]; char str[100]; vector<node> colum; int main() { while(scanf("%s",str)==1&&str[0]!='e') { memset(hasr,false,sizeof(hasr)); memset(hasc,false,sizeof(hasc)); memset(hasp,false,sizeof(hasp)); for(int i=0; i<9; i++) for(int j=0; j<9; j++) { if(str[i*9+j]!='.') { int k=str[i*9+j]-'0'; hasr[i][k]=true; hasc[j][k]=true; hasp[i/3 *3+j/3][k]=true; } } int m=4*9*9; int n=0; Link.init(m); for(int i=0; i<9; i++) for(int j=0; j<9; j++) { int k=0; if(str[i*9+j]!='.') k=str[i*9+j]-'0'; if(k!=0) { n++; colum.clear(); node dot; dot.k=k; dot.x=i; dot.y=j; dot.c=i*9+j+1; colum.push_back(dot); dot.c=81+i*9+k; colum.push_back(dot); dot.c=162+j*9+k; colum.push_back(dot); dot.c=243+(i/3*3+j/3)*9+k; colum.push_back(dot); Link.addRow(n,colum); }else { node dot; dot.x=i;dot.y=j; for(int k=1; k<=9; k++) { if(hasr[i][k]==false &&hasc[j][k]==false && hasp[i/3*3+j/3][k]==false) { dot.k=k; colum.clear(); n++; dot.c=i*9+j+1; colum.push_back(dot); dot.c=81+i*9+k; colum.push_back(dot); dot.c=162+j*9+k; colum.push_back(dot); dot.c=243+(i/3*3+j/3)*9+k; colum.push_back(dot); Link.addRow(n,colum); } } } } Link.dfs(0); for(int i=0; i<9;i++) for(int j=0; j<9; j++) printf("%d",Link.ans[i][j]); puts(""); } return 0; }