题意:把一个9行9列的网格,
再细分为9个3*3的子网格,要求每行、每列、每个子网格内都只能使用一次1~9中的一个数字,即每行、每列、每个子网格内都不允许出现相同的数字。
思路:
用三个数组进行标记每行、每列、每个子网格已用的数字,用于剪枝
bool row[10][10]; //row[i][x] 标记在第i行中数字x是否出现了
bool col[10][10]; //col[j][y] 标记在第j列中数字y是否出现了
bool grid[10][10]; //grid[k][z] 标记在第k个3*3子格中数字z是否出现了
DFS试探,下一层匹配失败则回溯
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#define PI acos(-1)
#define eps 0.00000001
using namespace std;
int a[11][11];
char s[11];
int Lvis[11][11],Rvis[11][11],vis[11][11];
int flag=0;
int DFS(int x,int y)
{
if(x==10)
return 1;
if(!a[x][y])
{
int k=(x-1)/3*3+(y-1)/3+1;
for(int i=1; i<=9; i++)
{
if(!Rvis[x][i]&&!Lvis[y][i]&&!vis[k][i])
{
a[x][y]=i;
Rvis[x][i]=Lvis[y][i]=vis[k][i]=1;
if(y==9) ///遍历下一层
flag=DFS(x+1,1);
else
flag=DFS(x,y+1);
if(flag==0) ///flag==0 表示下一层匹配失败 需要回溯
{ ///说明上面的赋值有问题
a[x][y]=0;
Rvis[x][i]=Lvis[y][i]=vis[k][i]=0;
}
}
}
}
else
{
if(y==9)
flag=DFS(x+1,1);
else
flag=DFS(x,y+1);
if(flag==0) ///flag==0 表示下一层匹配失败 需要回溯
///说明上面的赋值有问题
return 0;
else
return 1;
}
if(!a[x][y]) ///表示匹配失败了
return 0;
else
return 1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
flag=0;
memset(vis,0,sizeof(vis));
memset(Lvis,0,sizeof(Lvis));
memset(Rvis,0,sizeof(Rvis));
for(int i=1; i<=9; i++)
{
scanf("%s",s);
for(int j=1; j<=9; j++)
{
a[i][j]=s[j-1]-'0';
if(a[i][j])
{
int k=(i-1)/3*3+(j-1)/3+1;
Rvis[i][a[i][j]]=1;
Lvis[j][a[i][j]]=1;
vis[k][a[i][j]]=1;
}
}
}
DFS(1,1);
for(int i=1; i<=9; i++)
{
for(int j=1; j<=9; j++)
{
printf("%d",a[i][j]);
}
printf("\n");
}
}
return 0;
}