poj3074,3076 数独!(DLX)

本文探讨了使用跳舞链算法解决9*9数独问题的方法,详细解释了模型构建过程,包括状态存储、覆盖问题转化及决策过程。通过实例演示算法实现数独解的寻找。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大意:求解规模为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();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值