建图转成0/1矩阵。
就是先dfs把一个区域的块标号一下。
然后十字链表搞DLX...其实方法暴力了。据说直接建链表就行。我们这方法用C++会TLE,G++能过。感谢HDU超强服务器。
PS:这题我们卡了一个地方,就是找到解的时候必须马上记录,如下面代码的oo数组。不能最后再输出,因为找到解后还会继续回溯的,会破坏o数组。可惜样例看不出来……卡了好久才过的。
#include <algorithm>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
using namespace std;
int head=0;
const int INF=10000000;
const int MAX=750*350;
int dir[4]= {16, 32, 64, 128};
int tt[4][2]=
{
{-1, 0},
{0, 1},
{1, 0},
{0, -1}
};
struct node
{
int oo[100];
int mat[750][350], tor[750], toc[750], dig[750];
int n, m, o[1010], c[MAX], s[MAX], u[MAX], d[MAX], l[MAX], r[MAX], row[MAX];
int cnt, rowh;
int g[15][15];
int id[15][15];
int Num[15][15];
int hl;
int res;
void makegragh()
{
int nn, i, j, k, row, col, qua, pos, num;
memset(mat, 0, sizeof(mat));
n=1;
m=324;
cnt=0;
for(i=1; i<=9; i++)
{
for(j=1; j<=9; j++)
{
row=i;
col=j;
qua=id[i][j]+1;
pos=(i-1)*9+j;
if(Num[i][j]==0)
{
for(k=1; k<=9; k++)
{
tor[n]=i;
toc[n]=j;
dig[n]=k;
mat[n][(row-1)*9+k]=1;
mat[n][81+(col-1)*9+k]=1;
mat[n][162+(qua-1)*9+k]=1;
mat[n++][243+pos]=1;
}
}
else
{
tor[n]=i;
toc[n]=j;
num=Num[i][j];
dig[n]=num;
mat[n][(row-1)*9+num]=1;
mat[n][81+(col-1)*9+num]=1;
mat[n][162+(qua-1)*9+num]=1;
mat[n++][243+pos]=1;
}
cnt++;
}
}
n--;
}
void myremove(const int &cur)
{
l[r[cur]]=l[cur];
r[l[cur]]=r[cur];
for(int i=d[cur]; i!=cur; i=d[i])
{
for(int j=r[i]; j!=i; j=r[j])
{
u[d[j]]=u[j];
d[u[j]]=d[j];
--s[c[j]];
}
}
}
void myresume(const int &cur)
{
for(int i=u[cur]; i!=cur; i=u[i])
{
for(int j=l[i]; j!=i; j=l[j])
{
++s[c[j]];
u[d[j]]=j;
d[u[j]]=j;
}
}
l[r[cur]]=cur;
r[l[cur]]=cur;
}
void dfs(const int &k)
{
if(res>1)
return ;
// if (k>81) return;
if (r[head]==head)
{
res++;
if (res==1)
{
for (int i=0; i<81; i++) oo[i]=o[i];
sort(oo, oo+81);
}
return ;
}
int ms=INF, cur=0;
for(int t=r[head]; t!=head; t=r[t])
{
if(s[t]<ms)
{
ms=s[t];
cur=t;
}
}
myremove(cur);
for(int i=d[cur]; i!=cur; i=d[i])
{
o[k]=row[i];
for(int j=r[i]; j!=i; j=r[j])
myremove(c[j]);
dfs(k+1);
if(res>1)
return ;
for(int j=l[i]; j!=i; j=l[j])
myresume(c[j]);
}
if(res>1)
return ;
myresume(cur);
return ;
}
void dfs1(int x, int y, int hh)
{
id[x][y]=hh;
for(int i=0; i<4; i++)
{
if(dir[i]&g[x][y])
continue;
int x1=x+tt[i][0];
int y1=y+tt[i][1];
if((x1<1)||(y1<1)||(x1>9)||(y1>9))
continue;
if(id[x1][y1]!=-1)
continue;
dfs1(x1, y1, hh);
}
}
void init()
{
res=hl=0;
memset(id, -1, sizeof(id));
for(int i=1; i<=9; i++)
{
for(int j=1; j<=9; j++)
{
scanf("%d", &g[i][j]);
Num[i][j]=g[i][j];
for(int k=3; k>=0; k--)
{
if(Num[i][j]>=dir[k])
Num[i][j]-=dir[k];
}
// g[i][j]-=Num[i][j];
}
}
for(int i=1; i<=9; i++)
{
for(int j=1; j<=9; j++)
if(id[i][j]==-1)
{
dfs1(i, j, hl++);
}
}
head=0;
makegragh();
memset(s, 0, sizeof(s));
for(int i=head; i<=m; i++)
{
r[i]=(i+1)%(m+1);
l[i]=(i-1+m+1)%(m+1);
u[i]=d[i]=i;
}
cnt=m+1;
for(int i=1; i<=n; i++)
{
rowh=-1;
for(int j=1; j<=m; j++)
if(mat[i][j])
{
s[j]++;
u[cnt]=u[j];
d[u[j]]=cnt;
u[j]=cnt;
d[cnt]=j;
row[cnt]=i;
c[cnt]=j;
if(rowh==-1)
{
l[cnt]=r[cnt]=cnt;
rowh=cnt;
}
else
{
l[cnt]=l[rowh];
r[l[rowh]]=cnt;
r[cnt]=rowh;
l[rowh]=cnt;
}
cnt++;
}
}
}
void print()
{
if(res==0)
printf("No solution\n");
else if(res>1)
{
printf("Multiple Solutions\n");
}
else
{
// sort(o, o+81);
for(int i=0; i<9; i++)
{
for(int j=0; j<9; j++)
{
printf("%d", dig[oo[i*9+j]]);
}
printf("\n");
}
}
}
} dlx;
int Case;
void solve()
{
Case++;
dlx.init();
printf("Case %d:\n", Case);
dlx.dfs(0);
dlx.print();
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
solve();
return 0;
}