仅50行Python代码!数独求解!4秒!

可读性极高,直接上代码

递归求解

import numpy as np
from copy import deepcopy
def solve_recursion(pad, only_one_solve=True):
    '''递归求法'''
    pad = deepcopy(pad)
    pad = np.array(pad)
    pos = [-1, -1]  # 用来存放第一个未知数的位置
    possible = []  # 第一个未知数的位置可能的取值
    solves = []  # 解集
    if pad.max() > 9 or pad.min() < 0 or pad.shape != (9, 9):  # 异常保护
        raise ValueError("wtf with input value?")
    for y in range(9):  # 得到第一个未知数的位置
        if pos[0] != -1 and pos[1] != -1:  # 如果已经找到第一个未知数的位置
            break
        for x in range(9):
            if pad[y][x] == 0:
                pos = [x, y]
                break
    if pos[0] == -1 and pos[1] == -1:  # 第一个未知数的位置没找到,说明已经没有未知数了,已经解完
        print("find")
        return [pad]
    for k in range(1, 9 + 1):
        x = pos[0]
        y = pos[1]
        # 这一行内是否有k
        row = pad[y, :]
        if k in row:
            continue
        # 这一列内是否有k
        col = pad[:, x]
        if k in col:
            continue
        # 九宫格内是否有k
        box = pad[y - y % 3:y - y % 3 + 3, x - x % 3:x - x % 3 + 3]  # 切片出九宫格
        if k in box:
            continue
        possible.append(k)  # 这个位置为k时与当前已知情况不冲突
    if len(possible) == 0:  # 填什么都不满足当前的情况,无解
        return None
    for i in range(len(possible)):
        y = pos[1]
        x = pos[0]
        pad[y][x] = possible[i]  # 假设这个位置的数
        ret = solve_recursion(pad, only_one_solve=only_one_solve)  # 递归求解
        if ret is None:  # 无解
            pass
        elif isinstance(ret, list) and len(ret) == 0:  # 还没有解
            pass
        else:  # 解集
            if only_one_solve:
                return ret
            for j in range(len(ret)):
                solves.append(ret[j])
    return solves

传入参数:
pad,9x9二维list,pad[y][x]即x,y处对应的值,0表示未知,1-9对应1-9。
only_one_solve:True:求到一个解就直接中断求解,False:求完所有的解
返回值:
solves:解集list

求解所谓世界最难数独
求解所谓世界最难数独

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Python求解数独(Sudoku)通常会使用回溯算法或启发式搜索策略。以下是一个简单的概述: 1. **回溯算法**:这是一种递归的方法,从第一个空格开始,尝试填入数字1到9,然后检查每一、每一列和每一个宫格(3x3的小九宫格)是否都包含这9个数字一次。如果发现冲突,则回溯到上一步,尝试下一个数字。这个过程一直持续到找到一个合法的数独解决方案或者所有可能的数字都尝试过仍无解。 2. **启发式搜索**:如使用A*搜索,会优先填充那些规则更明确的位置(如、列、宫格已完全填满的区域),并在搜索过程中维护一个启发式函数(如最小剩余数法),帮助找到最快接近解决方案的状态。 在Python中,可以使用`numpy`库来创建和操作二维数组,`pandas`处理数据结构,还有自定义的数据结构(如`dict`或`set`)来存储候选数字。下面是一个简单的回溯算法示例: ```python import numpy as np def solve_sudoku(board): empty_cells = find_empty_cells(board) if not empty_cells: return True # 解决了,返回True row, col = empty_cells for num in range(1, 10): if is_safe(board, row, col, num): board[row][col] = num if solve_sudoku(board): return True board[row][col] = 0 # 回溯:移除刚才填入的数 return False # 辅助函数 def find_empty_cells(board): for i in range(9): for j in range(9): if board[i][j] == 0: return (i, j) # 返回第一个空格的坐标 return None def is_safe(board, row, col, num): # 检查、列、宫格 return all(board[row, j] != num for j in range(9)) and \ all(board[i, col] != num for i in range(row, row + 3, 3)) and \ all(board[i, j] != num for j in range(col, col + 3, 3)) # 示例: board = np.array([[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]]) if solve_sudoku(board): print("Solution:") print(board) else: print("No solution exists.") ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值