洛谷 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;
}

posted @ 2022-02-11 13:19  PandaBlack  阅读(89)  评论(0)    收藏  举报