Sudoku对数独非常感兴趣,今天他在书上看到了几道数独题:
给定一个由33的方块分割而成的99的表格(如图),其中一些表格填有1-9的数字,其余的则为空白(数字0为空白)。请在空白表格中填入数字1-9使得99表格的每行、每列、每个33块内无重复数字。
Input
第一行输入一个整数T,表示样例数量。对于每个样例, 一共9行, 表示数独表格的每一行。接下来每一行输入一个字符串表示数独表格的每一行的9个数字。数独表格中空白用数字0表示。
Output
对于每组样例,输出完整的数独表格,即数独表格的每一个空白都按规定填满数字。如果答案不唯一,输出任何一个答案就行。
Sample Input
1
103000509
002109400
000704000
300502006
060000050
700803004
000401000
009205800
804000107
Sample Output
143628579
572139468
986754231
391542786
468917352
725863914
237481695
619275843
854396127
提示
可能会有多组解,输出其中一种即可。
刚开始拿到这道题的时候其实是有点懵逼的,完全不知道如何下手,看到了网上一个大佬的解答,才感觉茅塞顿开。但大佬的文章对解答过程相对来说讲的较少,而且现在没找到当时看的博客,没办法转载,遂自己写一篇。
思路:
//刚开始没有出来的原因是存储的下标没有控制好 做题脑子不清楚
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int heng[10][10];
int zong[10][10];
int squa[10][10];
int pos[10][10]={
0,0,0,0,0,0,0,0,0,0,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9,};
int sq[10][10];
int x,m;
int dfs(int x,int y)
{
if(x==10)
return 1;
bool flag;
if(sq[x][y])
{
if(y == 9) flag = dfs(x+1,1);
else flag = dfs(x,y+1);
if(flag) return 1;
else return 0;
}
else{
for(int i=1;i<=9;i++)
{
if(!heng[x][i] && !zong[y][i] && !squa[pos[x][y]][i])
{
sq[x][y] = i;
heng[x][i] = 1;
zong[y][i] = 1;
squa[pos[x][y]][i] = 1;
if(y==9) flag = dfs(x+1,1);
else flag = dfs(x,y+1);
if(flag) return 1;
else
{
sq[x][y] = 0; //第一次忘了这句
heng[x][i] = 0; //回溯过程很重要
zong[y][i] = 0;
squa[pos[x][y]][i] = 0;
//return 0; 没有必要 我们要继续进行下面的for循环
}
}
}
}
return 0;
}
int main()
{
scanf("%d",&m);
while(m--)
{
x=0;
memset(heng,0,10*10);
memset(zong,0,10*10);
memset(squa,0,10*10);
char ch[10];
for(int i=1;i<=9;i++)
{
scanf("%s",ch);
for(int j=0;j<9;j++)
{
x = ch[j]-'0';
heng[i][x] = 1;
zong[j+1][x] = 1;
squa[pos[i][j+1]][x]=1;
sq[i][j+1]=x; //这里第一次出现错误
}
}
dfs(1,1);
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)
{
printf("%d",sq[i][j]);
}
printf("\n");
}
}
return 0;
}