洛谷 SP13980 题解
题目传送门
题意:
给定 \(n\) 个 \(9×9\) 的九宫格数独,对于每个数独,求出每个数独的解的数量,如果只有一个解,输出数独的唯一解。
思路:
-
SP13980 这道题可以用 DFS 深度优先搜索来做,因为深搜可以进行回溯,如果一个数填错可以倒回来重新填,如果填到最后全部正确,解的数量增加。
-
在判断行列是否重复时,我们可以定义两个 \(bool\) 标记数组,当该行/列填充数字时,就进行标记。
-
在判断宫内数字是否重复时,我们可以用数学中判断数独所在宫的序号的方法,逐个数字填充标记即可(公式见下)。
-
在数独中求一个宫的序号,可以用以下公式求解:
我们先假设行数为 \(x\),列数为 \(y\)。则:
所在宫序号=(x-1)/3*3+(y-1)/3+1
(注: 这道题和P1784 数独的思路完全一样,都可以用 DFS 来做。)
code:
#include <bits/stdc++.h>
using namespace std;
bool mp[15][15];
int vx[15][15];
bool vy[15][15],vc[15][15],vt[15][15];//表示每行,每列,每个格子
long long n,cnt;
void dfs(int x,int y){
if(mp[x][y]){ //已经访问过
if(x==9&&y==9){ //填写完成
cnt++;
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
vt[i][j]=mp[i][j];
}
if(y==9) dfs(x+1,1);
else dfs(x,y+1);
}
else{ //if(!mp[x][y])
for(int i=1;i<=9;i++){
if(!vx[x][i]&&!vy[y][i]&&!vc[(x-1)/3*3+(y-1)/3+1][i]){ //这个格子还未填写过
vx[x][i]=1;
vy[y][i]=1;
vc[(x-1)/3*3+(y-1)/3+1][i]=1;
mp[x][y]=i;
if(x==9&&y==9){
cnt++;
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
vt[i][j]=mp[i][j];
}
if(y==9) dfs(x+1,1); //继续递归填下一个
else dfs(x,y+1);
mp[x][y]=0; //回溯
vx[x][i]=0;
vy[y][i]=0;
vc[(x-1)/3*3+(y-1)/3+1][i]=0;
}
}
}
}
int main(){
cin>>n;
while(n--){
memset(vy,0,sizeof(vy));
memset(vx,0,sizeof(vx));
memset(vc,0,sizeof(vc));
cnt=0;
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
cin>>mp[i][j];
vx[i][mp[i][j]]=1;
vy[j][mp[i][j]]=1;
vc[(i-1)/3*3+(j-1)/3+1][mp[i][j]]=1;
}
}
dfs(1,1);
cout<<cnt<<endl;
if(cnt==1){
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++)
cout<<vt[i][j]<<" ";
cout<<endl;
}
}
}
return 0;
}
本文来自博客园,作者:PandaBlack,转载请注明原文链接:https://www.cnblogs.com/liu-black/p/sp13980-tijie.html