大致题意:
九宫格问题,也有人叫数独问题
把一个9行9列的网格,再细分为9个3*3的子网格,要求每行、每列、每个子网格内都只能使用一次1~9中的一个数字,即每行、每列、每个子网格内都不允许出现相同的数字。
0是待填位置,其他均为已填入的数字。
要求填完九宫格并输出(如果有多种结果,则只需输出其中一种)
如果给定的九宫格无法按要求填出来,则输出原来所输入的未填的九宫格
解题思路:
DFS试探,失败则回溯
用三个数组进行标记每行、每列、每个子网格已用的数字,用于剪枝
bool row[10][10]; //row[i][x] 标记在第i行中数字x是否出现了
bool col[10][10]; //col[j][y] 标记在第j列中数字y是否出现了
bool grid[10][10]; //grid[k][x] 标记在第k个3*3子格中数字z是否出现了
row 和 col的标记比较好处理,关键是找出grid子网格的序号与 行i列j的关系
即要知道第i行j列的数字是属于哪个子网格的
首先我们假设子网格的序号如下编排:
由于1<=i、j<=9,我们有: (其中“/”是C++中对整数的除法)
令a= i/3 , b= j/3 ,根据九宫格的 行列 与 子网格 的 关系,我们有:
不难发现 3a+b=k
即 3*(i/3)+j/3=k
有了这个推导的关系式,问题的处理就变得非常简单了,直接DFS即可
(以上是神牛的思路,只要是grid数组适用的太精辟了)
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#pragma warning(disable : 4996)
int n;
int map[10][10];
bool row[10][10]; //记录每行的数字是否可行
bool col[10][10]; //记录没列的数字是否可行
bool grid[10][10]; //记录每个九宫格的数字是否可行
void CreateMap()
{
char str[10] = {0};
for(int i = 0; i < 9; i++)
{
scanf("%s", str);
for(int j = 0; j < 9; j++)
{
map[i][j] = str[j] - '0';
if(map[i][j] != 0)
{
int num = map[i][j];
int k = 3 * (i / 3) + j / 3; // 这个公式很关键。这是求每个点对应的九宫格
row[i][num] = true;
col[j][num] = true;
grid[k][num] = true;
}
}
}
}
bool dfs(int i,int j)
{
bool flag = false;
if(i == 9) return true;
if(map[i][j] != 0)
{
if(j == 8)
{
flag = dfs(i + 1, 0);
}
else
{
flag = dfs(i, j + 1);
}
if(flag) //在这回溯,但不改变map的值,只起到一个传递的作用
return true;
else
return false;
}
else
{
int k = 3 * (i / 3) + j / 3;
for(int x = 1; x <= 9; x++)
{
if(!row[i][x] && !col[j][x] && !grid[k][x])
{
map[i][j] = x;
row[i][x] = true;
col[j][x] = true;
grid[k][x] = true;
if(j == 8)
{
flag = dfs(i + 1, 0);
}
else
{
flag = dfs(i, j + 1);
}
if(!flag) //这也是一个回溯
{
map[i][j] = 0;
row[i][x] = false;
col[j][x] = false;
grid[k][x] = false;
}
else
{
return true;
}
}//if
}//for
}
return false;
}
void output()
{
for(int i = 0; i < 9; i++)
{
for(int j = 0; j < 9; j++)
{
printf("%d", map[i][j]);
}
printf("\n");
}
}
int main()
{
freopen("in.txt","r",stdin);
scanf("%d", &n);
while(n--)
{
memset(row, false, sizeof(row));
memset(col, false, sizeof(col));
memset(grid, false, sizeof(grid));
CreateMap();
dfs(0, 0);
output();
}
return 0;
}