HJ44 Sudoku 数独 ”思维 搜索“

数独要求:在横、竖、3x3矩阵内0-9不可重复出现

重点思路实现方法是,填入一个数后下一步推算基于前面已经填好的数值的新矩阵。
相当于在这一过程中不断更新初始值用于下一步计算。

递归穷举,从第一个空开始填;再更新矩阵填下一个值,一直到最后一个空填完。

回溯:

查错花最多时间在:回溯没重置0导致错误。“递归要缩小规模,回溯要重置或父节点...”
尝试错误需要回溯,回复需要有一个父亲指标,(从链表通过父亲节点回溯中得到启发)

 1 '''
 2 测试案例
 3 m=[[0, 9, 2, 0, 0, 1, 7, 6, 3],
 4 [0, 0, 3, 7, 6, 2, 9, 8, 5],
 5 [0, 0, 7, 3, 5, 9, 4, 1, 2],
 6 [6, 2, 4, 1, 9, 5, 3, 7, 8],
 7 [7, 5, 9, 8, 4, 3, 1, 2, 6],
 8 [1, 3, 8, 6, 2, 7, 5, 9, 4],
 9 [2, 7, 1, 5, 3, 8, 6, 4, 9],
10 [3, 8, 6, 9, 1, 4, 2, 5, 7],
11 [0, 0, 5, 2, 7, 6, 8, 3, 1]]
12 m=[[0, 9, 5, 0, 2, 0, 0, 6, 0],
13 [0, 0, 7, 1, 0, 3, 9, 0, 2],
14 [6, 0, 0, 0, 0, 5, 3, 0, 4],
15 [0, 4, 0, 0, 1, 0, 6, 0, 7],
16 [5, 0, 0, 2, 0, 7, 0, 0, 9],
17 [7, 0, 3, 0, 9, 0, 0, 2, 0],
18 [0, 0, 9, 8, 0, 0, 0, 0, 6],
19 [8, 0, 6, 3, 0, 2, 1, 0, 5],
20 [0, 5, 0, 0, 7, 0, 2, 8, 3]]
21 '''
22 m=[]
23 for i in range(9):    
24     m.append(list(map(int,input().split())))
25 
26 def renew(item):#判断i所在的3x3矩阵并返回矩阵值;
27     #第一个3x3矩阵每个元素下标除以3向下取整为0,第二个3x3矩阵横坐标取整为0,纵坐标为1;
28     #第三个3x3矩阵横坐标取整为0,纵坐标为2;第四个3x3矩阵横坐标取整为1,纵坐标为0,继续类推。
29     renew_grid=[m[i][j] for i in range(item[0]//3*3,item[0]//3*3+3) \
30                 for j in range(item[1]//3*3,item[1]//3*3+3)]
31     renew_row=m[item[0]]
32     mTranspose=list(zip(*m))
33     renew_col=mTranspose[item[1]]        
34     return renew_grid,renew_row,renew_col
35 def recursion(get0):
36     if not get0:
37         return True
38     renew_grid,renew_row,renew_col=renew(get0[0])
39     for j in range(1,10):
40 '''
41         if m[0][7]==6:
42             print(j,get0[0])
43             for i in m:    
44                 print(" ".join(map(str,i)))
45 '''
46         if j not in renew_grid and j not in renew_row and j not in renew_col:
47             m[get0[0][0]][get0[0][1]] =j #更新m矩阵的值 
48             if recursion(get0[1:]):#get0路径跟踪,顺利就去除第一个元素继续跟着
49                 return True     
50             else:
51                 m[get0[0][0]][get0[0][1]] =0#回溯要重置0,否则不可实现
52 get0=[]
53 for i in range(len(m)) :
54     for j in range(len(m[0])):
55         if m[i][j]==0:
56             get0.append((i,j))
57 renew_grid,renew_row,renew_col=renew(get0[0])
58 recursion(get0)
59 for i in m:    
60     print(" ".join(map(str,i)))

 代码行数优化

可把上述代码的renew函数通过下面优化,得到正在填充节点的行列和3x3矩阵。通过“”set()-“”技巧

1 def value(m, x, y):    
2     i, j = x//3, y//3    
3     grid = [m[i*3+r][j*3+c] for r in range(3) for c in range(3)]
4     row_val = m[x]
5     col_val = list(zip(*m))[y]    
6     val = set([i for i in range(1,10)]) - set(grid) - set(row_val) - set(col_val)
7     return list(val)

 

posted @ 2023-05-04 19:37  Aneverforget  阅读(37)  评论(0编辑  收藏  举报