希望得到优化的方法
项目分为两个文件:
1. sudoku.py用于接受题目输入以及输出一个表示答案的二维数组
2. plt_show会接受这个二维数组并将其可视化
可以接受任意矩形的题目输入,且不需要输入其它参数
只能解决存在每一步迭代都存在确定解的情况
对于小规模的题目,例如30x30,完成计算通常只需要小于一秒的时间
对于大规模的题目,例如50x50,可能会需要超过20分钟的计算时间,且参与计算的列表
all_sequences体积可能达到几十G,所以对于大型题目(max_size > Storage_mode_threshold)
通过硬盘存储中间变量而不直接使用内存:
if max_size <= Storage_mode_threshold:
all_sequences.append(result)
else:
np.save(f'save/{file_counter}_{segment}.npy', result)
file_counter += 1
del result
gc.collect()
运行逻辑是:
1. 计算每一行和列所有可能的答案排列
2. 将每一行和列从answer中取出作为master,将该行或列所有排列作为作为slaves
清洗slaves中与不与master重叠的组合(比如answer为真,而slaves为假则剔除)
将清洗过后的所有slaves逻辑与,结果为真的项则答案(answer)在此项为真
所有slaves逻辑或,结果为假的项则答案在此项为假
将清洗过的slaves覆盖原slaves,剪枝
3.将确定的目标写入答案中,缩小解空间。判断答案中是否还有未知项,若有,则继续迭代
4.将答案(answer)可视化
sudoku.py
import numpy as np
import plt_show
import time
import gc
rows = [
[3, 3, 2, 2], [1, 3, 1, 2], [6, 1], [2, 3, 1, 1, 3], [3, 4, 1, 7],
[3, 4, 3, 5], [4, 5, 3, 6], [3, 4, 6, 3], [4, 11, 3, 1], [5, 2, 7],
[9, 7], [3, 9, 10], [2, 4, 3, 7], [2, 1, 3, 6, 2], [1, 5, 1, 3, 2],
[2, 3, 1, 1, 2], [6, 6, 2], [4, 1, 8, 1, 2], [8, 7, 1, 1], [5, 6, 3, 1, 2],
[3, 12, 3, 1, 1], [17, 1, 7], [2, 4, 8, 10], [6, 3, 7, 2], [3, 2, 3, 4, 1, 2],
[5, 2, 4], [4, 3, 1, 2], [4, 3, 2, 5], [3, 3, 1, 5], [7, 3, 7]
]
columns = [
[1, 1, 4, 3], [3, 1, 1, 4, 3], [4, 1, 3, 5, 1], [3, 1, 1, 1, 1, 5, 1], [7, 2, 5, 1],
[9, 1, 4, 1], [1, 6, 6, 1], [4, 12], [3, 3, 1, 4, 6], [1, 6, 3, 1, 7, 3],
[8, 3, 1, 1, 5], [1, 15, 5], [1, 7, 3, 3, 2], [3, 1, 1, 10, 3], [4, 2, 2, 6, 3],
[2, 3, 13], [5, 2, 3, 5], [5, 1, 4, 2], [6, 1, 3, 1], [7, 3],
[6, 2, 3], [6, 5], [2, 1, 1, 4, 1, 4], [1, 3, 1, 5, 6, 2], [4, 1, 7, 1, 3, 1, 1],
[5, 1, 1, 1, 1, 9], [5, 1, 3, 3], [5, 3, 3], [5, 3, 1, 1, 4, 4], [2, 1, 3, 8, 4]
]
all_segments = rows + columns
size_r = len(columns)
size_c = len(rows)
max_size = max(size_c, size_r)
Storage_mode_threshold = 40
answer = np.zeros((size_c, size_r), dtype=np.uint8)
all_sequences = []
def find_sequences(segments, size):
result = []
def backtrack(arr, index, segment):
if not segment:
result.append(arr.copy())
return
length = segment[0]
# 遍历可能的起始位置
for i in range(index, size - length + 1):
if arr[i - 1]:
continue
# 标记当前片段为 1
arr[i:i + length] = True
backtrack(arr, i + length