传送门:poj2676 Sudoku
题目大意
九宫格问题,也有人叫数独问题
把一个9行9列的网格,再细分为9个3*3的子网格,要求每行、每列、每个子网格内都只能使用一次1~9中的一个数字,即每行、每列、每个子网格内都不允许出现相同的数字。
0是待填位置,其他均为已填入的数字。
要求填完九宫格并输出(如果有多种结果,则只需输出其中一种)
如果给定的九宫格无法按要求填出来,则输出原来所输入的未填的九宫格
解题思路
因为每当改变一个数的时候,它所在的一行和一列还有所在的小方格不能出现相同的数字,所以就通过dfs枚举每个数字。
每一行每一列很好理解,但是每一个方格我们就要看下面的图,分为图中的9个区域
我们分别来用
rowExist[i][x] 表示第i行是否存在x
colExist[j][x]表示第j列是否存在x
gridExist[k][x]表示第k个方格是否存在x
0<=i,j,k<=8;
前面两个行和列都是很好解决的但是小方格grid还是有计算一下
通过简单地关心不难得到:k = 3*(i/3) + j/3;(这是从下标为0开始的时候计算的)
有了这个之后,我们就每个枚举就可以了。
AC代码
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 200005;
#define lson left,mid,rt<<1
#define rson mid+1,right,rt<<1|1
int trueChess[10][10];
bool rowExist[10][10];
bool colExist[10][10];
bool gridExist[10][10];
bool dfs(int x,int y)
{
if(x==9)
return true;
bool flag = false;
//如果不用填写,接着向后一个遍历
if(trueChess[x][y])
{
if(y==8)
flag = dfs(x+1,0);
else
flag = dfs(x,y+1);
if(flag)
return true;
else
return false;
}
else//如果是待填写的,就进行枚举填入
{
int k = 3*(x/3) + y/3;
for(int i=1; i<=9; i++)
{
if(!rowExist[x][i] && !colExist[y][i] && !gridExist[k][i])
{
trueChess[x][y] = i;
rowExist[x][i] = true;
colExist[y][i] = true;
gridExist[k][i] = true;
if(y==8)
flag = dfs(x+1,0);
else
flag = dfs(x,y+1);
if(!flag)//回溯
{
trueChess[x][y] = 0;
rowExist[x][i] = false;
colExist[y][i] = false;
gridExist[k][i] = false;
}
else
return true;
}
}
}
return false;
}
int main()
{
int t;
scanf("%d",&t);
char chess[10][10];
while(t--)
{
memset(rowExist,false,sizeof rowExist);
memset(colExist,false,sizeof colExist);
memset(gridExist,false,sizeof gridExist);
for(int i=0; i<9; i++)
{
scanf("%s",chess[i]);
for(int j=0; j<9; j++)
{
trueChess[i][j] = chess[i][j] - '0';
if(trueChess[i][j])
{
int k = 3*(i/3) + j/3;
//如果不是待填写的,就标记上
rowExist[i][trueChess[i][j]] = true;
colExist[j][trueChess[i][j]] = true;
gridExist[k][trueChess[i][j]] = true;
}
}
}
//从左上角开始遍历
dfs(0,0);
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
printf("%d",trueChess[i][j]);
printf("\n");
}
}
return 0;
}