大意:求解规模为9*9的数独问题
分析:对于每一行,每一列,每一宫,数字1,2。。。9都需出现1次且只能是一次,可转化为精确覆盖问题,用跳舞链解决
建模型:
行数为9*9*9,数独中,第i行j列放数字k的状态存储在图中第(i*9+j)*9+k行中
列数为9*9+9*9+9*9+9*9,
其中第一个9*9代表第i格是否已填满,如果已经填了,有且仅有一个g[cur][i*9+j]=1;否则会有1-9共9个,用精确覆盖再决策,这样能保证每格都被填充。
用第二个9*9确保每行的数字唯一且均出现一次 g[cur][81+i*9+k]=1表示第i行能够填k
第三个9*9确保每列的数字唯一且出现一次
第四个9*9确保每宫的数字唯一出现1次
#include<stdio.h>
#include<string.h>
#define MAXN 1050
int n,m;
int U[MAXN*MAXN];
int D[MAXN*MAXN];
int L[MAXN*MAXN];
int R[MAXN*MAXN];
int C[MAXN*MAXN]; //to see node[i] belong to which column
int row[MAXN*MAXN]; // to see node[i] belong to which row
int ans[MAXN],ansnum;
int nn[MAXN];
int mm[MAXN];
bool map[MAXN][MAXN];
const int head=0;
char str[100];
void read_data(){
memset(mm,0,sizeof(mm));
for(int i=1;i<=m;i++){
R[i-1]=L[i+1]=U[i]=D[i]=i;
}
R[m]=0;
R[head]=1;
int id=m+1;
int x,Rhead;
for(int i=0;i<n;i++){
Rhead=-1;
for(int j=0;j<m;j++){
if(map[i][j]==true){
x=j+1;
mm[x]++;
row[id]=i;
C[id]=x;
//update the column
U[id]=U[x];
D[U[x]]=id;
U[x]=id;
D[id]=x;
//update the row
if(Rhead==-1){
L[id]=R[id]=id;
Rhead=id;
}
else {
L[id]=L[Rhead];
R[L[Rhead]]=id;
L[Rhead]=id;
R[id]=Rhead;
}
id++;
}
}
}
}
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];
mm[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]){
mm[C[j]]++;
U[D[j]]=j;
D[U[j]]=j;
}
}
L[R[c]]=c;
R[L[c]]=c;
}
bool dfs(int cur){
if(R[head]==head){
return true;
}
int s=999999999,c;
for(int t=R[head];t!=head;t=R[t]){
if(mm[t]<s){
s=mm[t];
c=t;
}
}
remove(c);
for(int i=D[c];i!=c;i=D[i]){
ans[row[i]]=true;
for(int j=R[i];j!=i;j=R[j]){
remove(C[j]);
}
if(dfs(cur+1))return true;
ans[row[i]]=false;
for(int j=L[i];j!=i;j=L[j]){
resume(C[j]);
}
}
resume(c);
return false;
}
void addrow(int i,int j,int k){
int cur=(i*9+j)*9+k;
map[cur][i*9+j]=true;
map[cur][81+i*9+k]=true;
map[cur][81+81+j*9+k]=true;
int rc=i/3;
int lc=j/3;
map[cur][81+81+81+(rc*3+lc)*9+k]=true;
}
void build_graph(){
memset(map,false,sizeof(map));
for(int i=0;i<81;i++){
if(str[i]=='.'){
int a=i/9;
int b=i%9;
for(int k=0;k<9;k++)addrow(a,b,k);
}
else {
int a=i/9;
int b=i%9;
addrow(a,b,str[i]-'1');
}
}
}
void solve(){
build_graph();
read_data();
memset(ans,false,sizeof(ans));
dfs(0);
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
for(int k=0;k<9;k++)
if(ans[(i*9+j)*9+k])printf("%d",k+1);
}
}
printf("\n");
}
int main(){
n=9*9*9;
m=(81+9*9+9*9+9*9); //first 81 present 81 grids;next 9*9 present line ,column,blocks state;
while(scanf("%s",str)!=EOF){
if(strcmp(str,"end")==0)break;
solve();
}
}