poj3074,3076 数独!(DLX)

来源:互联网 发布:淘宝客佣金套路 编辑:程序博客网 时间:2024/05/22 13:50

大意:求解规模为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 1050int 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 columnint row[MAXN*MAXN]; // to see node[i] belong to which rowint 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();    }}

原创粉丝点击