题目链接
题目大意
输入n个数独,空格用0表示,填数独(符合的一种方案即可)。
分析
类似于八皇后的简单搜索题,用DFS回溯法求解。
将空格的位置都记录下来,1个1个填下去,填不下去就清空换其他数字。
关键进行可行性剪枝:
row[i][j]:记录第i行数字j是否可填
column[i][j]:记录第i列数字j是否可填
block[i][j]:记录第i个九宫格数字j是否可填
代码
#include <iostream>
#include <cstring>
using namespace std;
bool row[10][10],column[10][10],block[10][10],flag;
int s[10][10],cnt;
struct
{
int x,y;
}p[730]; //记录空格的坐标
int num(int x,int y) //返回(x,y)属于第几个九宫格
{
if (1<=x&&x<=3&&1<=y&&y<=3) return 1;
if (1<=x&&x<=3&&4<=y&&y<=6) return 2;
if (1<=x&&x<=3&&7<=y&&y<=9) return 3;
if (4<=x&&x<=6&&1<=y&&y<=3) return 4;
if (4<=x&&x<=6&&4<=y&&y<=6) return 5;
if (4<=x&&x<=6&&7<=y&&y<=9) return 6;
if (7<=x&&x<=9&&1<=y&&y<=3) return 7;
if (7<=x&&x<=9&&4<=y&&y<=6) return 8;
if (7<=x&&x<=9&&7<=y&&y<=9) return 9;
}
void Init()
{
cnt=0;
flag=false;
memset(row,true,sizeof(row));
memset(column,true,sizeof(column));
memset(block,true,sizeof(block));
}
void Print()
{
for (int i=1;i<=9;i++)
{
for (int j=1;j<=9;j++)
cout<<s[i][j];
cout<<endl;
}
}
void dfs(int t)
{
if (t==cnt+1) //当所有空格都填完了
{
flag=true;//找到1个答案就不用搜索了
Print();
}
if (flag) return;
int x,y;
x=p[t].x;y=p[t].y;
for (int i=1;i<=9;i++)
if (row[x][i]&&column[y][i]&&block[num(x,y)][i])
{
s[x][y]=i;
row[x][i]=column[y][i]=block[num(x,y)][i]=false;
dfs(t+1);
if (flag) return;
s[x][y]=0;
row[x][i]=column[y][i]=block[num(x,y)][i]=true;//回溯,清空标记
}
return;
}
int main()
{
int test,i,j;
char ch;
cin>>test;
while (test--)
{
Init();
for (i=1;i<=9;i++)
for (j=1;j<=9;j++)
{
cin>>ch;
s[i][j]=ch-'0';
if (!s[i][j])
{
p[++cnt].x=i;
p[cnt].y=j;
}
else
{
row[i][s[i][j]]=false;
column[j][s[i][j]]=false;
block[num(i,j)][s[i][j]]=false;
}
}
dfs(1);
}
return 0;
}