解一个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;
}