求一个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;
}