Dijkstra算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止,适用于求解有向图的最短路径。在每次扩展跟新时获得一个最短路径的点,然后下一次更新时以该点作为中介点更新与之相联的点,同时用一个表记录求得了解值的点,避免下一次循环时被重复处理。
下面,我将用Python举例运用这种思路求解数独。
问题描述:
数独由9×9个小方格组成,每三行三列相交为一宫,每格需填入1到9中的一个数字,其中,部分位置上的数已给出,要求在剩下的格子中填入数字,需满足每一行、每一列、每一宫中的数字均不重复。
解题思路:
先用列表记录所有点可能的解,已知点的解为所给值,未知点的可能解为1、2、3、4、5、6、7、8、9,每次循环用已求解的点来更新该点所在行、列、宫的所有其他待求点的可能解,即在其他点的可能解中去除该点的值。同时用一个表来记录所有点的状态,默认为True,当已求得解值并且更新了所有与该点关联的点的可能的解值后,状态值置为False,该点退出循环。
先建立数据结构,sukudo表用于记录每个点的可能的解的列表,processed表用于记录每个点的状态,标记每个点是否未解,Jiugongge字典帮助判断每个点更新了所在行和所在列以后后,其所在的九宫格内剩下的四个与之关联的点的坐标的偏移量。
sukudo=[[],[],[],[],[],[],[],[],[]] #记录每个点的可能的解
processed=[[],[],[],[],[],[],[],[],[]] #用于标记每个点是否未解
Jiugongge={0:[1,2],1:[-1,1],2:[-2,-1]} #辅助求解与某点在同一个九宫格内的点
update函数用于更新有为一解的点所在的行、列、宫的所有关联点的解。
def update(m,n,num):
for i in range(9):
if num in sukudo[m][i] and n!=i: #更新坐标(m,n)点所在的行的点的解
sukudo[m][i].remove(num)
if num in sukudo[i][n] and m!=i:#更新坐标(m,n)点所在的列的点的解
sukudo[i][n].remove(num)
for i in Jiugongge[m%3]: #更新坐标(m,n)点所九宫格剩下四点的解
for j in Jiugongge[n%3]:
if num in sukudo[m+i][n+j]:
sukudo[m+i][n+j].remove(num)
notEnd()函数通过遍历processed表中所有点的状态来判断是否存在点的唯一解未求得,返回True表示还有点未求得,程序继续,返回False则所有点求解完毕。
def notEnd():
for i in range(9):
if True in processed[i]:
return True
return False
主程序先通过用户输入获得待求解的数独,然后把所有点的初始可能解存放在sukudo表中,并初始化processed表所有值为True,然后循环更新,每当发现一个点的可能解只有一个并且没有用该点解更新过所在的行、列、宫时,更新,并将该点在processed表中的状态置为False,避免循环处理。
i=0
while i<9:
print('请输入第'+str(i+1)+'行的数字,未知数字输入0')
a=input()
if a.isdecimal() and len(a)==9: #输入格式判断
for j in range(9):
processed[i].append(True) #初始化processed表所有值为True
if a[j]=='0': #待求点
sukudo[i].append([1,2,3,4,5,6,7,8,9])
else: #已知点
sukudo[i].append([int(a[j])])
i=i+1
else:
print('格式错误,请重新输入',end='')
while notEnd():
for i in range(9):
for j in range(9):
#当sukudo表中点(i,j)仅有一可能解,且没有用该点解更新过所在的行、列、宫
if len(sukudo[i][j])==1 and processed[i][j]:
update(i,j,sukudo[i][j][0]) #用该点解更新过所在的行、列、宫
processed[i][j]=False #将该点在processed表中的状态置为False
print('结果为:')
for i in sukudo:
for j in i:
print(str(j[0]),end='')
print('\n')
测试结果如下:
与笔算结果一致:
但是此算法只能求得只有一个解的情况,不能求解有多个解的数独。
参考资料:
Dijkstra算法实现最快路径