大致题意:
九宫格问题,也有人叫数独问题
把一个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; }