python学习笔记(四):回溯法解决数独问题

python学习笔记(四):回溯法解决数独问题

数独定义

数独,整个网格又分成9个3×3的小正方形网格,每个格子有一个数字(1~9),数独满足如下要求:

(1)每个数字在每一行只出现一次

(2)每个数字在每一列只出现一次

(3)每个数字在每个3×3的小区域中也只出现一次

如下图所示。
在这里插入图片描述

回溯法的一般步骤

while(结束条件未满足)
{
	if(本层可行的解决方案存在):
			执行
			if(本层为最后一层):
					输出结果
					return    
            else:
            	进入下一层
	else:
			return(回溯到上层)
}            

代码

import numpy as np

#以二维列表形式初始数独
grid = [[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,0,0]]

#判断在第y行第x列填n是否可行
def possible(y,x,n):
    global grid
    #判断同一行是否有重复的
    for i in range(0,9):
        if grid[y][i] == n:
            return False
    #判断同一列是否有重复的
    for i in range(0,9):
        if grid[i][x] == n:
            return False
    #判断同一区域内是否有重复的
    x0 = (x//3)*3
    y0 = (y//3)*3
    for i in range(0,3):
        for j in range(0,3):
            if grid[y0+i][x0+j] == n:
                return False
    return True
    
#填数
def solve():
    global grid
    for y in range(9):
        for x in range(9):
        	#找第一个空格
            if grid[y][x] == 0:
                #从1-9中找能填的数,找到了就填进去,填下一个空;
                #找不到就return,告诉上一层不能这样填,要清0重填
                for n in range(1,10):
                    if possible(y,x,n):
                        grid[y][x] = n
                        solve()
                        grid[y][x] = 0
                return 
    #当没有空的时候退出循环并打印结果
    print(np.matrix(grid),'\n')


输出:

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

[[5 3 4 6 7 8 9 1 2]
 [6 7 2 1 9 5 3 4 8]
 [1 9 8 3 4 2 5 6 7]
 [8 5 9 7 6 1 4 2 3]
 [4 2 6 8 5 3 7 9 1]
 [7 1 3 9 2 4 8 5 6]
 [9 6 1 5 3 7 2 8 4]
 [2 8 7 4 1 9 6 3 5]
 [3 4 5 2 8 6 1 7 9]] 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值