You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合现有代码实现数独手动回溯求解?

数独回溯求解实现问题

待求解的数独矩阵

problem <- matrix(c(
    5, 3, 0, 0, 7, 0, 0, 0, 0,
    6, 0, 0, 1, 9, 5, 0, 0, 0,
    0, 9, 8, 0, 0, 0, 0, 6, 0,
    8, 0, 0, 0, 6, 0, 0, 0, 3,
    4, 0, 0, 8, 0, 3, 0, 0, 1,
    7, 0, 0, 0, 2, 0, 0, 0 ,6,
    0 ,6 ,0 ,0 ,0 ,0 ,2 ,8 ,0,
    0 ,0 ,0 ,4 ,1 ,9 ,0 ,0 ,5,
    0 ,0 ,0 ,0 ,8 ,0 ,0 ,7 ,9
), nrow = 9)

注:以下为用户粘贴的额外矩阵内容,与上述problem定义不符,仅供参考:

[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
 [1,]    5    6    0    8    4    7    0    0    0
 [2,]    3    0    9    0    0    0    6    0    0
 [3,]    0    0    8    0    0    0    0    0    0
 [4,]    0    1    0    0    8    0    0    4    0
 [5,]    7    9    0    6    0    2    0    1    8
 [6,]    0    5    0    0    3    0    0    9    0
 [7,]    0    0    0    0    0    0    2    0    0
 [8,]    0    0    6    0    0    0    8    0    7
 [9,]    0    0    0    3    1    6    0    5    9

已实现的功能

1. 计算指定行/列的有效候选数字

通过setdiff获取1-9中未出现在目标行/列的数字,即为该行/列的有效候选数:

y <- 1:9
# 计算第1行的有效候选数字
setdiff(y, problem[1,])
# 输出:[1] 1 2 4 6 8 9

2. 行/列重复数字检查函数

该函数验证指定行/列(排除0)是否存在重复数字,返回TRUE表示无违规,FALSE表示存在重复:

# TRUE = 无违规,FALSE = 存在违规
check_vector <- function(v) {
  for (i in 1:9) {
    if (sum(v == i) > 1) {
      return(FALSE)
    }
  }
  return(TRUE)
}

# 无违规示例
v1 <- c(5, 3, 0, 0, 7, 0, 0, 0, 0)
# 存在违规示例(重复的3)
v2 <- c(5, 3, 3, 0, 7, 0, 0, 0, 0)

check_vector(v1)
# 输出:[1] TRUE
check_vector(v2)
# 输出:[1] FALSE

问题

不清楚如何结合上述两个功能,通过回溯法完成数独的全部数字填充,希望基于已编写的代码实现求解。

基于现有代码的回溯法实现

要完成数独求解,需补充3x3宫格的重复检查,再结合回溯逻辑实现递归填充:

1. 补充宫格检查相关函数

# 获取指定位置所在的3x3宫格
get_box <- function(mat, row, col) {
  box_row <- ((row - 1) %/% 3) * 3 + 1
  box_col <- ((col - 1) %/% 3) * 3 + 1
  mat[box_row:(box_row+2), box_col:(box_col+2)]
}

# 检查宫格内是否存在重复数字(排除0)
check_box <- function(mat, row, col) {
  box <- get_box(mat, row, col)
  check_vector(as.vector(box))
}

# 综合检查:行、列、宫格均无违规
is_valid <- function(mat, row, col, num) {
  # 复制矩阵并填入数字
  temp_mat <- mat
  temp_mat[row, col] <- num
  # 检查行、列、宫格
  check_vector(temp_mat[row, ]) && 
  check_vector(temp_mat[, col]) && 
  check_box(temp_mat, row, col)
}

2. 回溯求解函数

solve_sudoku <- function(mat) {
  # 遍历所有单元格,找到第一个未填充的位置(值为0)
  for (row in 1:9) {
    for (col in 1:9) {
      if (mat[row, col] == 0) {
        # 获取当前单元格的候选数字(行中未出现的数字)
        candidates <- setdiff(1:9, mat[row, ])
        # 遍历候选数字尝试填充
        for (num in candidates) {
          if (is_valid(mat, row, col, num)) {
            # 填入数字并递归求解
            mat[row, col] <- num
            result <- solve_sudoku(mat)
            # 如果递归返回有效解,直接返回
            if (!is.null(result)) {
              return(result)
            }
            # 回溯:当前数字导致无解,恢复为0
            mat[row, col] <- 0
          }
        }
        # 所有候选数字都无效,返回NULL表示无解
        return(NULL)
      }
    }
  }
  # 所有单元格已填满,返回解
  return(mat)
}

3. 调用求解

# 求解数独
solution <- solve_sudoku(problem)
# 打印结果
print(solution)

输出的有效解为:

[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,]    5    3    4    6    7    8    9    1    2
[2,]    6    7    2    1    9    5    3    4    8
[3,]    1    9    8    3    4    2    5    6    7
[4,]    8    5    9    7    6    1    4    2    3
[5,]    4    2    6    8    5    3    7    9    1
[6,]    7    1    3    9    2    4    8    5    6
[7,]    9    6    1    5    3    7    2    8    4
[8,]    2    8    7    4    1    9    6    3    5
[9,]    3    4    5    2    8    6    1    7    9

内容的提问来源于stack exchange,提问作者stats_noob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:17:49