求解数独sudoku问题 9*9c++代码_用回溯解决数独

在这篇文章中,我将介绍一种使用回溯的数独求解算法。如果你不知道回溯,那么只需刷过上一篇文章。

Sudoku是一个9x9矩阵,填充数字1到9,每个行,列和子矩阵(3x3)的每个数字都是1到9.我们提供了部分填充的9x9矩阵,必须填充其中每个剩余的细胞。例如,下面给出了数独问题。

87b729d8d2a5072550fa4bc2511b3f5f.png

其解决方案如下。

17cdb5949a2c4f69e2129f50e39b6949.png

您可以看到每个行,列和子矩阵(3x3)包含从1到9的每个数字。因此,我们还可以得出结论,如果数独满足以下任何条件,则认为数据被错误填充:

  1. 任何行包含多次相同的数字。
  2. 任何列都包含多次相同的数字。
  3. 任何3x3子矩阵都具有不止一次的相同数字。

在回溯中,我们首先从一个子解决方案开始,如果这个子解决方案没有给我们一个正确的最终答案,那么我们回过头来改变我们的子解决方案。我们将以类似的方式解决我们的数独。我们将遵循的步骤是:

  • 如果没有未分配的单元格,则数独已经解决。我们将回归真实。
  • 否则,我们将使用1到9之间的数字填充未分配的单元格,以便在任何行,列或3x3子矩阵中不存在冲突。
  • 现在,我们将尝试填充下一个未分配的单元格,如果这成功发生,那么我们将返回true。
  • 否则,我们将返回并更改用于填充单元格的数字。如果没有满足需要的数字,那么我们将返回false,因为没有这个数独的解决方案。

所以,让我们编写代码吧。

class Sudoku{ private static final int SIZE = 9; private static int[][] matrix = { {6,5,0,8,7,3,0,9,0}, {0,0,3,2,5,0,0,0,8}, {9,8,0,1,0,4,3,5,7}, {1,0,5,0,0,0,0,0,0}, {4,0,0,0,0,0,0,0,2}, {0,0,0,0,0,0,5,0,3}, {5,7,8,3,0,1,0,2,6}, {2,0,0,0,4,8,9,0,0}, {0,9,0,6,2,5,0,8,1} }; private static void printSudoku() { for(int i=0;i

代码说明

最初,我们只是为Sudoku制作一个矩阵,并用0填充未分配的单元格。因此,矩阵包含Sudoku问题,值为0的单元格是空白单元格。

print_sudoku() →这只是打印矩阵的功能。

number_unassigned →此函数找到一个空单元格,并使变量'row'和'col'等于该单元格的索引。在C中,我们使用指针来改变传递给该函数的变量(row,col)的值(通过引用传递)。在Java和Python中,我们返回一个包含这些值的数组(或Python列表)。所以,这个函数告诉我们是否有任何未分配的单元格。如果有任何未分配的单元格,那么此函数也会告诉我们该单元格的索引。

is_safe(int n, int r, int c)→此函数检查我们是否可以将值'n'放入单元格(r,c)中。我们这样做是首先检查行'r'中是否有任何单元格的值为'n'或不是 - if(matrix[r][i] == n)。然后我们检查在'c'列中是否有任何值为'n'的单元格 - if(matrix[i][c] == n)。最后,我们正在检查子矩阵。 (r/3)*3 给出了行r的起始索引。例如,如果'r'的值是2,那么它在从(0,0)开始的子矩阵中。同样,我们得到了起始列的值(c/3)*3。因此,如果一个单元格是(2,2),那么这个单元格将在一个从(0,0)开始的子矩阵中,我们得到这个值(c/3)*3和(r/3)*3。在获得起始索引之后,我们可以轻松地遍历子矩阵以检查我们是否可以将值'n'放在该子矩阵中。

solve_sudoku()→这是解决数独并使用回溯的实际功能。我们首先通过使用该number_unassigned函数检查是否有任何未分配的单元格 ,如果没有未分配的单元格,则解决数独。 number_unassigned 函数还给出了空单元的索引。因此,如果有任何空白单元格,那么我们将尝试用1到9之间的值填充此单元格。我们将使用它 is_safe 来检查是否可以填充该单元格中的特定值。找到一个值后,我们将尝试解决数独的其余部分solve_sudoku。如果此值无法解决其余问题,我们将返回并尝试此单元格的其他值matrix[row][col]=0;。循环将尝试单元格中的其他值。

整理不易,请大家多多收藏加关注 ,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值