Time Limit: 2000MS | Memory Limit: 65536K | |||
Total Submissions: 14917 | Accepted: 7372 | Special Judge |
Description

Input
Output
Sample Input
1 103000509 002109400 000704000 300502006 060000050 700803004 000401000 009205800 804000107
Sample Output
143628579 572139468 986754231 391542786 468917352 725863914 237481695 619275843 854396127
数独问题,一看很明显就知道是搜索。
首先考虑从左上角的空白格子开始填数字的DFS搜索。所填的数字应该是所在行,列和方块中都没有填过的数字。
用三个数组进行标记每行、每列、每个子网格已用的数字,用于剪枝
bool row[10][10]; //row[i][x] 标记在第i行中数字x是否出现了
bool col[10][10]; //col[j][y] 标记在第j列中数字y是否出现了
bool squ[10][10]; //grid[k][x] 标记在第k个3*3子格中数字z是否出现了
row 和 col的标记比较好处理,关键是找出grid子网格的序号与 行i列j的关系
即要知道第i行j列的数字是属于哪个子网格的。
关键是要找出怎么通过横纵坐标判断是哪一个子块。
只要推出了公式: k =3* ((i-1)/3)+(j-1)/3+1
i、j、k分别为行、列、块编号,从1开始。
如果从0开始就是k=3*(i/3)+j/3
知道了这点,以后,这个问题和八皇后问题有着异曲同工的感觉,但是需要很强的剪枝能力。
然后就是dfs的一般写法,如果能放继续搜下一个位置,如果不能就回溯,把标记改回来,直到最后递归完成。。
代码比较丑,我也将就着看。。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
bool row[10][10]; //横向 row[i][x]标记在第i行中数字x是否出现了
bool col[10][10]; //纵向 col[j][y] 标记在第j列中数字y是否出现了
bool squ[10][10]; //方块 squ[k][x] 标记在第k个3*3子格中数字z是否出现了
int map[10][10];
bool dfs(int x,int y)
{
if(x==10)
return true;
bool flag=false;
if(map[x][y])
{
if(y==9) flag=dfs(x+1,1);
else flag=dfs(x,y+1);
if(flag)
return true;
else
return false;
}
else
{
int k=3*((x-1)/3)+(y-1)/3+1;
for(int i=1;i<=9;i++) //从1-9中枚举能放的数
{
if(!row[x][i] && !col[y][i] && !squ[k][i])
{
map[x][y]=i;
row[x][i]=true;
col[y][i]=true;
squ[k][i]=true;
if(y==9)
flag=dfs(x+1,1);
else
flag=dfs(x,y+1);
if(flag)
return true;
else
{
map[x][y]=0;
row[x][i]=false;
col[y][i]=false;
squ[k][i]=false;
}
}
}
}
return false;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(row,0,sizeof(row));
memset(col,0,sizeof(col));
memset(squ,0,sizeof(squ));
char t[10][10];
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)
{
cin>>t[i][j];
map[i][j]=t[i][j]-'0';
if(map[i][j])
{
int k=3*((i-1)/3)+(j-1)/3+1;
row[i][map[i][j]]=true;
col[j][map[i][j]]=true;
squ[k][map[i][j]]=true;
}
}
}
dfs(1,1);
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)
printf("%d",map[i][j]);
printf("\n");
}
}
return 0;
}