B32 Dancing Links 舞蹈链 数独

视频链接:133 Dancing Links 舞蹈链 数独_哔哩哔哩_bilibili

Luogu P1784 数独

 

 

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=3245; //点729*4+列头324
int n,m,cnt; //矩阵的长,宽,点的编号
int u[N],d[N],l[N],r[N]; //每个点的上下左右
int row[N],col[N]; //每个点所在行,列
int h,t;  //每行的头,尾指针
int s[N]; //每列的节点数
int ans[N]; //选了那些行
int a[10][10];//数独的数

void init(){ //初始化第0行的列表头
  for(int y=0; y<=m; y++){
    u[y]=d[y]=y;
    l[y]=y-1; r[y]=y+1;
  }
  l[0]=m; r[m]=0; cnt=m+1; //下一个点的编号
}
void link(int x,int y){ //在x行y列插入点 
  row[cnt]=x; col[cnt]=y; s[y]++;
  u[cnt]=u[y]; //y...u[y]←→cnt←→y
  d[u[y]]=cnt;
  d[cnt]=y;
  u[y]=cnt;
  l[cnt]=t; //h...t←→cnt←→h
  r[t]=cnt;
  r[cnt]=h;
  l[h]=cnt;
  t=cnt++; //t指向cnt, 然后cnt+1
}
void remove(int y){ //删除y列与关联行
  r[l[y]]=r[y], l[r[y]]=l[y]; 
  for(int i=d[y]; i!=y; i=d[i])   //向下
    for(int j=r[i]; j!=i; j=r[j]) //向右
      u[d[j]]=u[j], d[u[j]]=d[j], s[col[j]]--;
}
void resume(int y){ //恢复y列与关联行
  r[l[y]]=y, l[r[y]]=y;  
  for(int i=u[y]; i!=y; i=u[i])   //向上
    for(int j=l[i]; j!=i; j=l[j]) //向左
      u[d[j]]=j, d[u[j]]=j, s[col[j]]++;
}
bool dance(int dep){
  if(r[0]==0){
    for(int i=0,x,y,v;i<dep;i++){
      x=(ans[i]-1)/9/9; //链表行→数独
      y=(ans[i]-1)/9%9;
      v=(ans[i])%9;
      a[x][y]=v?v:9; 
    }
    for(int i=0;i<=8;i++){
      for(int j=0;j<=8;j++)printf("%d ",a[i][j]);
      puts("");
    }
    return true;
  }
  int y=r[0]; //找到点最少的列
  for(int i=r[0];i;i=r[i]) if(s[i]<s[y])y=i;
  remove(y);
  for(int i=d[y];i!=y;i=d[i]){
    ans[dep]=row[i];
    for(int j=r[i];j!=i;j=r[j]) remove(col[j]);
    if(dance(dep+1)) return true;
    for(int j=l[i];j!=i;j=l[j]) resume(col[j]);
  }
  resume(y); 
  return false;
}
int main(){
  n=729; m=324;
  init();
  for(int i=0; i<9; i++){      //数独的行
    for(int j=0,x; j<9; j++){  //数独的列
      scanf("%d",&x);a[i][j]=x;
      for(int k=1; k<=9; k++){ //9个数
        if(x==0||x==k){
          h=t=cnt; //每行的第一个点
          int r=i*9*9+j*9+k; //数独→链表行
          link(r,i*9+j+1); 
          link(r,81*1+i*9+k); 
          link(r,81*2+j*9+k); 
          link(r,81*3+(i/3*3+j/3)*9+k);
        }
      }
    }
  }
  dance(0);
}

 

posted @ 2023-06-29 06:53  董晓  阅读(286)  评论(0编辑  收藏  举报