求一个9*9的数独的解,保证有唯一解。DLX模版题,做题的时候,我发现回溯时如果不是和搜的过程刚好逆回去的话,效率会降低不少,但这不影响正确性,不知道为什么。。。
#include <stdlib.h> #include <iostream> #include <stdio.h> #include <string.h> #include <vector> using namespace std; #define ll long long const int SLOT = 0; const int ROW = 1; const int COL = 2; const int SUB = 3; int encode(int type,int id,int num){ return type*81+id*9+num+1; } char mp[90]; const int maxnode=270000; const int maxn=350; const int maxr=750; struct dlx{ #define FOR(i,A,s) for(int i = A[s];i!=s;i=A[i]) int n,sz; int U[maxnode],D[maxnode],L[maxnode],R[maxnode]; int row[maxnode],col[maxnode]; int S[maxn]; //各列节点数 int ans[maxr]; int ansdep; void init(int n){ this->n=n; sz=0; memset(S,0,sizeof(S)); for(int i=0;i<=n;i++){ U[i]=D[i]=i; L[i]=i-1; R[i]=i+1; sz++; } L[0]=n; R[n]=0; } void addrow(int r,vector<int> newrow){ int first=sz; for(int i=0;i<newrow.size();i++){ int pos=newrow[i]; U[sz]=U[pos]; D[sz]=pos; U[pos]=sz; D[U[sz]]=sz; row[sz]=r; col[sz]=pos; S[pos]++; sz++; } for(int i=first;i<sz;i++){ L[i]=i-1; R[i]=i+1; } L[first]=sz-1; R[sz-1]=first; } void remove(int c){ R[L[c]]=R[c]; L[R[c]]=L[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; } } R[L[c]]=c; L[R[c]]=c; } bool dfs(int d){ if(R[0]==0){ ansdep=d; return 1; } int c=R[0]; //去满足一列 for(int i=c;i!=0;i=R[i]){ if(S[i]<S[c])c=i; } remove(c); FOR(i,D,c){ //遍历这一列 ans[d]=row[i]; FOR(j,R,i){ remove(col[j]); } if(dfs(d+1))return 1; FOR(j,L,i){ restore(col[j]); } } restore(c); return 0; } }solver; int main(){ while(cin>>mp){ if(mp[0]=='e'&&mp[1]=='n'&&mp[2]=='d')break; solver.init(324); for(int i=0;i<81;i++){ for(int k=1;k<=9;k++){ if(mp[i]==k+'0'||mp[i]=='.'){ vector<int> vec; vec.push_back(encode(SLOT,i/9,i%9)); vec.push_back(encode(ROW,i/9,k-1)); vec.push_back(encode(COL,i%9,k-1)); vec.push_back(encode(SUB,i/27*3+(i%9)/3,k-1)); solver.addrow( i*9+k-1 ,vec); } } } bool ok = solver.dfs(0); for(int i=0;i<81;i++){ int tmp=solver.ans[i]; int pos=tmp/9; mp[pos]=tmp%9+1+'0'; } for(int i=0;i<81;i++){ printf("%c",mp[i]); }cout<<endl; } return 0; }