目录
引言
图片展示
视频展示
针对校园导航问题的分析
关键技术和算法介绍
详细介绍:算法的实现
总结
代码
附件:Map.png
引言
本文主要通过详细的程序打印和作者的推理过程,描述作者对Floyd算法的理解,阐述其中的动态规划思想是如何进行和应用。作者使用Python简单、方便移动的可视化,与Floyd算法相结合,让用户对最短路径一目了然,阅读完本文作者的推理过程后,读者更能对Floyd其中的原理以及对动态规划思想更能深刻体会。
图片展示
视频展示
最短路径展示
针对校园导航问题的分析
本课题要解决的问题是如何在平面图上找出任意场所到达另一场所的最佳路径,要求是最短的路径、而且至少包括10个以上的场所、每个场所间有不同的路、以及界面需可视化。本课题也有一定的限制条件,即每两个场所的路长不能相同。进行本设计要达到的具体的目标为能够成功实现便捷地操作校园导航地图,通过点击就能直观地展现任意两个场所之间的最短路径。
关键技术和算法介绍
本文用到的关键技术是动态规划,动态规划就是可以将问题拆分成若干子问题并实时保存子问题已解决的答案的一种算法,这是它比分治法更优的地方,不用去重复从头开始计算。本课题所用程序的设计思想是使用Python语言,以Floyd算法的二维数组邻接矩阵为基础,通过不断刷新数组来记录各点到各点的中间点,最后通过反推获取最终最短的路径。
核心代码
#==========================================================================================
for k in range(10):
for i in range(10):
for j in range(10):
if AllZeroList[i][j]> AllZeroList[i][k] + AllZeroList[k][j]:
AllZeroList[i][j] = AllZeroList[i][k] + AllZeroList[k][j]
path[i][j] = path[k][j]
#==========================================================================================
网上有其他版本,如最后path[i][j] = path[k],这个可能会在一些小地方会出错,这种属于中间点实时更新的策略错误。
AllZeroList是表示路径长度二维数组,
Path是表示动态规划记录中间点的二维数组
i是行
j是列
k在我的理解看来,是用来帮助i和j的辅助参数,时而变成i即行,时而变成j即列,确保路径长度二维数组里的每个元素都可以全部遍历和判断。哈哈哈我就把k称为动态规划参数吧。
这个是详细打印观看版,你可以详细地观看里面变化,从而得出自己的规律
#====================================详细打印观看变化版====================================
for k in range(10):
for i in range(10):
for j in range(10):
if i>=7:
print("*************************************")
print("【测试】AllZeroList[i][j]:",AllZeroList[i][j])
print("【测试】AllZeroList[i][k]:",AllZeroList[i][k])
print("【测试】AllZeroList[k][j]:",AllZeroList[k][j])
print("k,i,j:",k,i,j)
if AllZeroList[i][j]> AllZeroList[i][k] + AllZeroList[k][j]:
print("\n\n------------------进入判断------------------")
AllZeroList[i][j] = AllZeroList[i][k] + AllZeroList[k][j]
for c in range(10):
print("path3:",path[c],end="\n")
print("【测试】k:",k)
print("【测试】i:",i)
print("【测试】j:",j)
print("【测试】path[k][j]:",path[k][j])
print("【测试】path[i][j]:",path[i][j])
path[i][j] = path[k][j]
print("-----------------------------------【测试】path[i][j]:",path[i][j])
for d in range(10):
print("path4:",path[d],end="\n")
#========================================================================================
详细介绍:算法的实现
- 绘制地图。
海龟turtle绘制地图路线。
根据地图路径创建二维数组邻接矩阵。
从自己到本身为0
两个点没有直接相连就设为无穷大inf
将地图各个路径长度导入
- 创建二维数组Path记录中心点
用i、j、k配合三个for循环比较地图已计算出来的各自距离的值,将AllZeroList[i][j]与AllZeroList[i][k]和AllZeroList[k][j]之和相比较,一旦大于这个和就将AllZeroList[i][k]和AllZeroList[k][j]之和赋给AllZeroList[i][j],并且需要同时更新中间点,将path[k][j]赋给path[i][j],让最短路径里的每个节点都不会出错。
- 创建存入两个点的方法,比较两个数,如果不相等就去找两点的中间点,然后将中间点作为新的y又开始新一轮的比较,其中每找一次中间点就记一次中间点的数是多少,直到x和y相等就停止,最后将记的中间点从后往前推,也就是我们要的最短路径。
- 海龟turtle重置,根据上面二维数组获取的最短路径对地图进行绘制,用蓝色线条显现出最短路径,从而完成实现可视化。
总结
Floyd算法就是使用动态规划的思想,利用3个for循环将AllZeroList[i][j]与AllZeroList[i][k]和AllZeroList[k][j]之和相比较,一旦大于这个和就将AllZeroList[i][k]和AllZeroList[k][j]之和赋给AllZeroList[i][j],并且需要同时更新中间点,将path[k][j]赋给path[i][j],让最短路径里的每个节点都不会出错。并创建存入任意两个点的方法,比较两个数,如果不相等就去找两点的中间点,然后将中间点作为新的y又开始新一轮的比较,其中每找一次中间点就记一次中间点的数是多少,直到x和y相等就停止,最后将记的中间点从后往前推,也就是我们要的最短路径。这就是Floyd弗洛伊德算法。
代码
import turtle
import time
from turtle import Turtle, mainloop
import numpy
import numpy as np
import sys
sys.setrecursionlimit(100000) #设置为十万,突破局限
import threading
flag=1
control=0
def BreakThroughTheLimitation():
print("1")
if __name__ == '__main__':
threading.stack_size(200000000)
thread = threading.Thread(target=BreakThroughTheLimitation)
thread.start()
##time.sleep(5)
turtle.hideturtle()
turtle.bgpic("Map.png")
turtle.setup(1800,920,0,0)
turtle.pensize(10)
turtle.speed(0)
turtle.delay(0) #调速
turtle.title("庄彦涛_校园导航Floyd算法")
#===============================================
def ChuFa(control): #1至2
turtle.up()
#提笔隐藏
turtle.goto(-500,-395)
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('1',font=("隶书",20,"bold"))
turtle.down()
## time.sleep(5)
turtle.up()
turtle.left(135)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(160):
turtle.fd(2)
turtle.hideturtle()
#===============================================
#===============================================
def Place1(control): #2至4
#提笔隐藏
turtle.up()
turtle.goto(-740,-145)
turtle.down()
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('2',font=("隶书",20,"bold"))
turtle.up()
turtle.right(120)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(170):
turtle.fd(2)
turtle.hideturtle()
#===============================================
#===============================================
def Place2(control): #4至1
#提笔隐藏
turtle.up()
turtle.goto(-395,-55)
turtle.down()
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('4',font=("隶书",20,"bold"))
turtle.up()
turtle.right(123)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(162):
turtle.fd(2)
turtle.hideturtle()
#===============================================
#===============================================
def Place3(control): #2至3
#提笔隐藏
turtle.up()
turtle.goto(-740,-145)
turtle.down()
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('2',font=("隶书",20,"bold"))
turtle.up()
turtle.left(175)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(180):
turtle.fd(2)
turtle.hideturtle()
#===============================================
#===============================================
def Place4(control): #3至5
#提笔隐藏
turtle.up()
turtle.goto(-590,215)
turtle.down()
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('3',font=("隶书",20,"bold"))
turtle.up()
turtle.right(80)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(180):
turtle.fd(2)
turtle.hideturtle()
#===============================================
#===============================================
def Place5(control): #5至4
#提笔隐藏
turtle.up()
turtle.goto(-225,135)
turtle.down()
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('5',font=("隶书",20,"bold"))
turtle.up()
turtle.right(120)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(110):
turtle.fd(2)
turtle.hideturtle()
#===============================================
#===============================================
def Place6(control): #4至6
#提笔隐藏
turtle.up()
turtle.goto(-395,-55)
turtle.down()
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('4',font=("隶书",20,"bold"))
turtle.up()
turtle.left(133)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(172):
turtle.fd(2)
turtle.hideturtle()
#===============================================
#===============================================
def ChuFa_1(control): #1至6
turtle.up()
#提笔隐藏
turtle.goto(-500,-395)
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('1',font=("隶书",20,"bold"))
turtle.down()
turtle.up()
turtle.left(35)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(280):
turtle.fd(2)
turtle.hideturtle()
#===============================================
#===============================================
def Place7(control): #5至6
#提笔隐藏
turtle.up()
turtle.goto(-225,135)
turtle.down()
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('5',font=("隶书",20,"bold"))
turtle.up()
turtle.right(80)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(130):
turtle.fd(2)
turtle.hideturtle()
#===============================================
#===============================================
def Place8(control): #5至9
#提笔隐藏
turtle.up()
turtle.goto(-225,135)
turtle.down()
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('5',font=("隶书",20,"bold"))
turtle.up()
turtle.left(60)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(200):
turtle.fd(2)
turtle.hideturtle()
#===============================================
#===============================================
def Place9(control): #6至7
#提笔隐藏
turtle.up()
turtle.goto(-20,-65)
turtle.down()
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('6',font=("隶书",20,"bold"))
turtle.up()
turtle.right(15)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(110):
turtle.fd(2)
turtle.hideturtle()
#===============================================
#===============================================
def Place10(control): #7至8
#提笔隐藏
turtle.up()
turtle.goto(230,-65)
turtle.down()
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('7',font=("隶书",20,"bold"))
turtle.up()
turtle.left(40)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(90):
turtle.fd(2)
turtle.hideturtle()
#===============================================
#===============================================
def Place11(control): #9至10
#提笔隐藏
turtle.up()
turtle.goto(190,250)
turtle.down()
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('9',font=("隶书",20,"bold"))
turtle.up()
turtle.right(35)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(220):
turtle.fd(2)
turtle.dot(60,"#ffdd20")
turtle.hideturtle()
#===============================================
#===============================================
def Place12(control): #8至10
#提笔隐藏
turtle.up()
turtle.goto(390,70)
turtle.down()
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('8',font=("隶书",20,"bold"))
turtle.up()
turtle.left(34)
if control == 0:
turtle.pencolor("#665f35")
else:
turtle.pencolor("#0000FF")
for i in range(16):
turtle.fd(2)
turtle.down()
for i in range(158):
turtle.fd(2)
turtle.dot(60,"#ffdd20")
turtle.pencolor("#665f35")
turtle.write('10',font=("隶书",20,"bold"))
turtle.hideturtle()
##===============================================
ChuFa(control)
Place1(control)
Place2(control)
Place3(control)
Place4(control)
Place5(control)
Place6(control)
ChuFa_1(control)
Place7(control)
Place8(control)
Place9(control)
Place10(control)
Place11(control)
Place12(control)
def distance():
turtle.up()
turtle.pencolor("#665f35")
#=================================================
turtle.goto(-650,-345)
turtle.write('40米',font=("simkai",20,"normal"))
#=================================================
#=================================================
turtle.goto(-650,-155)
turtle.write('50米',font=("simkai",20,"normal"))
#=================================================
#=================================================
turtle.goto(-520,-245)
turtle.write('50米',font=("simkai",20,"normal"))
#=================================================
#------------------------------------------------------------------------
#=================================================
turtle.goto(-380,80)
turtle.write('30米',font=("simkai",20,"normal"))
#=================================================
#=================================================
turtle.goto(-150,70)
turtle.write('30米',font=("simkai",20,"normal"))
#=================================================
#=================================================
turtle.goto(-280,-100)
turtle.write('50米',font=("simkai",20,"normal"))
#=================================================
#------------------------------------------------------------------------
#=================================================
turtle.goto(-480,200)
turtle.write('50米',font=("simkai",20,"normal"))
#=================================================
#=================================================
turtle.goto(-600,100)
turtle.write('70米',font=("simkai",20,"normal"))
#=================================================
#------------------------------------------------------------------------
#=================================================
turtle.goto(-200,-230)
turtle.write('100米',font=("simkai",20,"normal"))
#=================================================
#=================================================
turtle.goto(80,-120)
turtle.write('30米',font=("simkai",20,"normal"))
#=================================================
#=================================================
turtle.goto(330,-20)
turtle.write('20米',font=("simkai",20,"normal"))
#=================================================
#=================================================
turtle.goto(400,150)
turtle.write('40米',font=("simkai",20,"normal"))
#=================================================
#------------------------------------------------------------------------
#=================================================
turtle.goto(10,220)
turtle.write('80米',font=("simkai",20,"normal"))
#=================================================
#=================================================
turtle.goto(390,300)
turtle.write('90米',font=("simkai",20,"normal"))
#=================================================
distance()
x=0
y=0
def submit1():
global x
screen1 = turtle.Screen()
answer1 = screen1.textinput("庄彦涛_校园导航Floyd算法",\
"----------------------请输入出发地的编号----------------------")
if answer1 is None:
print("未输入编号!")
## screen1.clear()
## screen1.bye()
else:
print("好的!")
x=int(answer1)-1
def submit2():
global y
screen2 = turtle.Screen()
answer2 = screen2.textinput("庄彦涛_校园导航Floyd算法", \
"----------------------请输入目的地的编号----------------------")
if answer2 is None:
print("未输入编号!")
screen2.clear()
screen2.bye()
else:
print("好的!")
y=int(answer2)-1
f = float('inf') # float('inf')表示无穷大
print(f)
#因为整个地图有10个地点
AllZeroList=[[0] * 10 for i in range(10)] #全零二维数组 (n行,n列 ,填充数)
for d in range(10):
print("AllZeroList:",AllZeroList[d],end="\n")
B=[40,50,100,40,70,50,70,50,50,50,30,50,50,30,30,80,100,50\
,30,30,30,20,20,40,80,90,40,90]
Name="Judge"
for p in range(1,10+1):
Choose=Name+str(p)
if p==1:
Choose=[1,2,4,6] #是否相邻判断列表1
if p==2:
Choose=[2,3,4,1] #是否相邻判断列表2
if p==3:
Choose=[3,2,5] #是否相邻判断列表3
if p==4:
Choose=[4,1,2,5,6] #是否相邻判断列表4
if p==5:
Choose=[5,3,4,6,9] #是否相邻判断列表5
if p==6:
Choose=[6,1,4,5,7] #是否相邻判断列表6
if p==7:
Choose=[7,6,8] #是否相邻判断列表7
if p==8:
Choose=[8,7,10] #是否相邻判断列表8
if p==9:
Choose=[9,5,10] #是否相邻判断列表9
if p==10:
Choose=[10,9,8] #是否相邻判断列表10
print(Choose)
for q in range(1,10+1):
print("q:",q)
print("Choose[0]:",Choose[0])
if q==Choose[0]:
AllZeroList[p-1][q-1]=0
else:
if q in Choose:
AllZeroList[p-1][q-1]=1
else:
AllZeroList[p-1][q-1]=f
#用f来表示无穷大,即两个地点没有直接连在一起
print(" 1 2 3 4 5 6 7 8 9 10")
for e in range(10):
print("AllZeroList:",AllZeroList[e],end="\n")
print(B)
for p in range(1,10+1):
for q in range(1,10+1):
if AllZeroList[p-1][q-1]==1:
AllZeroList[p-1][q-1]=B.pop(0)
print("\n 1 2 3 4 5 6 7 8 9 10")
for f in range(10):
print("AllZeroList:",AllZeroList[f],end="\n")
path=[[i] * 10 for i in range(10)]
for b in range(10):
print("path1:",path[b],end="\n")
#=================================简化版===================================================================
##for k in range(10):
## for i in range(10):
## for j in range(10):
## if AllZeroList[i][j]> AllZeroList[i][k] + AllZeroList[k][j]:
## AllZeroList[i][j] = AllZeroList[i][k] + AllZeroList[k][j]
## path[i][j] = path[k][j]
#====================================================================================================
#详细打印观看变化版
for k in range(10):
for i in range(10):
for j in range(10):
if i>=7:
print("*************************************")
print("【测试】AllZeroList[i][j]:",AllZeroList[i][j])
print("【测试】AllZeroList[i][k]:",AllZeroList[i][k])
print("【测试】AllZeroList[k][j]:",AllZeroList[k][j])
print("k,i,j:",k,i,j)
if AllZeroList[i][j]> AllZeroList[i][k] + AllZeroList[k][j]:
print("\n\n------------------进入判断------------------")
AllZeroList[i][j] = AllZeroList[i][k] + AllZeroList[k][j]
for c in range(10):
print("path3:",path[c],end="\n")
print("【测试】k:",k)
print("【测试】i:",i)
print("【测试】j:",j)
print("【测试】path[k][j]:",path[k][j])
print("【测试】path[i][j]:",path[i][j])
path[i][j] = path[k][j]
print("-----------------------------------【测试】path[i][j]:",path[i][j])
for d in range(10):
print("path4:",path[d],end="\n")
print("\n")
for c in range(10):
print("path2:",path[c],end="\n")
route = []
change=0
def RouteOfTwoPlace(x,y):
print("==========新的一轮计算==========")
print(x)
print(y)
global route
global change
if x>y:
change=x
x=y
y=change
def AddRoute(x,y):
print("----------------")
print(route)
print("1x:",x)
print("-------------------------------------1y:",y)
if x!=y:
print("1path[x][y]:",path[x][y])
AddRoute(x,path[x][y])
print("*****\/*****")
print("2x:",x)
print("2y:",y)
print("*****/\*****")
print("最小的值从后往前反推,就像栈一样,羽毛球筒正着放进去,反着把羽毛球y拿出来,y加进route里:",y)
## return route.append(y+1)
return route.append(y)
#如果x和y相等那么此时的y就是最短路径上的其中一个路线点,加进route里
AddRoute(x,y)
route2=route
RouteStr=str(route)
RouteStr=RouteStr.replace(',','-->')
print(f"测试:从{x+1}到{y+1}的最短路径为:{RouteStr}")
print("\n\n++++++++++++++++++++++++++++++++++++++\n\n")
for t in range(len(route)):
route[t]+=1
RouteStr=str(route)
RouteStr=RouteStr.replace(',','-->')
print(f"展示给客户:从{x+1}到{y+1}的最短路径为:{RouteStr}")
for g in range(10):
print("AllZeroList:",AllZeroList[g],end="\n")
def submit3():
global y
global flag
screen3 = turtle.Screen()
answer3 = screen3.textinput("庄彦涛_校园导航Floyd算法", \
"------------是否继续测算? 是【除0外任意键】 否【0】----------------------")
print(type(answer3))
if answer3=='0':
print("已退出!")
flag=0
## screen2.clear()
## screen2.bye()
else:
print("继续测算中!")
while flag==1:
submit1()
submit2()
RouteOfTwoPlace(x,y)
print(route)
cat=[]
a=b=c=d=e=f=g=h=i=j=k=l=m=n=0
change2=""
unfold=0
while len(route):
cat.append(route.pop(0))
print(cat)
control=1
turtle.right(86)
if len(cat)==2:
if cat[0]>cat[1]:
change2=cat[1]
cat[1]=cat[0]
cat[0]=change2
unfold=1
if cat[0]==1 and cat[1]==2:
a=1
if cat[0]==2 and cat[1]==4:
b=1
if cat[0]==1 and cat[1]==4:
c=1
if cat[0]==2 and cat[1]==3:
d=1
if cat[0]==3 and cat[1]==5:
e=1
if cat[0]==4 and cat[1]==5:
f=1
if cat[0]==4 and cat[1]==6:
print("==========")
g=1
if cat[0]==1 and cat[1]==6:
h=1
if cat[0]==5 and cat[1]==6:
i=1
if cat[0]==5 and cat[1]==9:
j=1
if cat[0]==6 and cat[1]==7:
k=1
if cat[0]==7 and cat[1]==8:
l=1
if cat[0]==9 and cat[1]==10:
m=1
if cat[0]==8 and cat[1]==10:
n=1
cat.pop(0)
if unfold==1:
cat[0]=change2
print(cat)
print(a,b,c,d,e,f,g,h,i,j,k,l,m,n)
##turtle.left(31)
turtle.reset()
turtle.pensize(10)
ChuFa(a)
Place1(b)
Place2(c)
Place3(d)
Place4(e)
Place5(f)
Place6(g)
ChuFa_1(h)
Place7(i)
Place8(j)
Place9(k)
Place10(l)
Place11(m)
Place12(n)
distance()
submit3()