解一个9*9的数独,行和列和普通数独一样需要出现1~9,但是它的小区域不是方形的,而是一个不规则的面积为9的图形。
DLX模版题。位运算和dfs处理小区域的边界就不说了。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-1)*9+num; } int mp[12][12]; int sub[12][12]; const int maxnode=270000; const int maxn=350; const int maxr=750; int anscnt; void init(){ anscnt=0; memset(sub,0,sizeof(sub)); } 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 ans2[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; } void dfs(int d){ if(anscnt>1)return; if(R[0]==0){ ansdep=d; anscnt++; memcpy(ans2,ans,sizeof(ans)); return; } 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]); } dfs(d+1); FOR(j,L,i){ restore(col[j]); } } restore(c); } }solver; void dfs(int nn,int mm,int val){ //找上下左右 //u16 r32 d64 l128 if(sub[nn][mm])return; sub[nn][mm]=val; if( (mp[nn][mm]&16)==0){ dfs(nn-1,mm,val); } if( (mp[nn][mm]&32)==0){ dfs(nn,mm+1,val); } if( (mp[nn][mm]&64)==0){ dfs(nn+1,mm,val); } if( (mp[nn][mm]&128)==0){ dfs(nn,mm-1,val); } } int main(){ int t; cin>>t; int cas=0; while(t--){ init(); cas++; for(int i=1;i<=9;i++){ for(int j=1;j<=9;j++){ scanf("%d",&mp[i][j]); } } int subcnt=0; for(int i=1;i<=9;i++){ for(int j=1;j<=9;j++){ if(!sub[i][j]){ dfs(i,j,++subcnt); } } } // for(int i=1;i<=9;i++){ for(int j=1;j<=9;j++){ mp[i][j]&=15; } } solver.init(324); for(int i=1;i<=9;i++){ for(int j=1;j<=9;j++){ for(int k=1;k<=9;k++){ if(mp[i][j]==k||mp[i][j]==0){ vector<int> vec; vec.push_back(encode(SLOT,i,j)); vec.push_back(encode(ROW,i,k)); vec.push_back(encode(COL,j,k)); vec.push_back(encode(SUB,sub[i][j],k)); solver.addrow( (i-1)*81+(j-1)*9+(k-1) ,vec); } } } } solver.dfs(0); printf("Case %d:\n",cas); if(anscnt==0){ printf("No solution\n"); }else if(anscnt==1){ for(int i=0;i<81;i++){ int tmp=solver.ans2[i]; int nn=tmp/81; tmp-=nn*81; int mm=tmp/9; int val=tmp%9; mp[nn+1][mm+1]=val+1; } for(int i=1;i<=9;i++){ for(int j=1;j<=9;j++){ printf("%d",mp[i][j]); }printf("\n"); } }else{ printf("Multiple Solutions\n"); } } return 0; }