A*算法(超级详细讲解,附有举例的详细手写步骤)

97 篇文章 92 订阅
订阅专栏

背景:项目需要接触此算法,以下是一些自学成果,如有不足之处,欢迎指出,必虚心接受。做了一份PPT来汇报,此处直接使用自己PPT的截图。部分图片来源网络,如有侵权立马删除,以下博文仅作为学习笔记。后期又新增了完整PPT。

A*算法完整PTT_dujuancao11的博客-CSDN博客

A*算法入门 - Jacc.Kim - 博客园

目录

A*寻路算法 

A*算法解决什么问题

A*算法的基本原理

A*算法的详细原理

A*算法的详细原理之定义

​A*算法的详细原理之初始设定 

​A*算法的详细原理之寻路原理

A*算法的详细原理之结束条件

A*算法的寻路详细步骤

A*算法的举例说明 

A*算法的伪代码

A*算法的定义伪代码 (C++)

A*算法的寻路伪代码(C++)

Python+PyQt代码实现

代码内容(可运行)

运行结果 

可执行文件

拓展

Dijkstra算法和A*算法的比较


A*寻路算法 

A*算法解决什么问题

A*算法的基本原理

A*算法的详细原理

A*算法的详细原理之定义

A*算法的详细原理之初始设定 

A*算法的详细原理之寻路原理

A*算法的详细原理之结束条件

 

A*算法的寻路详细步骤

S(start)起点              E(End)终点

A*算法的举例说明 

如果还不懂的话,可以参考我手写的计算步骤,再不懂可以私信我。(手稿字有点丑) 

 

A*算法的伪代码

A*算法的定义伪代码 (C++)

int open_list;//一个记录下所有被考虑来寻找最短路径的格子
int close_list; //一个记录下不会再被考虑的格子
typedef struct point{
	bool Is_Wall;
	struct point* father;//父节点
	int G;// 表示从起点 A 移动到网格上指定方格的移动耗费 (上下左右,还可沿斜方向移动)
	int old_G;//旧G 第一次:从起点 A 直接移动到 A 四周方格的移动耗费 ;上次更新得到的G 
	int new_G; //新G  从起点 A 经过当前搜索中心点到其四周指定点的移动耗费 
	int H;//表示从指定的方格移动到终点 B 的预计耗费 (H 有很多计算方法, 这里我们设定只可以上下左右移动)
	int F=G+H;//表示该点的总耗费
}Point;
point* start_point;
point* end_point;
point* min_point; 
point* now_point; 

A*算法的寻路伪代码(C++)

//FindPath
do{
	//确定中心搜索点,上一个中心点关闭,新的中心点开启 
	查找:Find the minimumm "point" of "F" from the "open_list" center;
	"now_point" = "min_point";//minimumm point 
	"now_point"添加到"close_list";
	
	//新中心点的周围点开启,新中心点关闭 
	循环遍历:"now_point"相邻的周围8格"s_now_point"中的每一个;
	//这一块它指的就是now_point周围8点当前搜索点 s_now_point,为了简单直接用它表示 
	if (它不可通过||它已经在"close_list"中){
		什么也不做;
	} else if (它不在开启列表中){
		把它添加进"open_list";
		把"now_point"作为这它的"father",计算它的"F","G","H";
	}else if (它已经在开启列表中){//通过G来判断是否需要更新 
		if (new_G < old_G){
			更新它的"father"为当前中心搜索点"now_point";
			更新它的"G"与"F" ;
		} else{
			不更新,保持原来的"father", "G"与"F" ;
		} 
	}
} while(目标格"end_point"已经在"open_list"||"open_list"==NULL)
//存在路径:目标格"end_point"已经在"open_list"
//不存在路径: "open_list"==NULL,搜索了所有可能的点 

Python+PyQt代码实现

代码内容(可运行)

import time,sys
from PyQt5.QtWidgets import QDialogButtonBox,QDialog,QMainWindow,QGridLayout,QTextEdit,QLineEdit,QWidget, QMessageBox, QApplication,QLabel,QPushButton,QHBoxLayout,QVBoxLayout
from PyQt5.QtCore import Qt,QTimer,QObject,pyqtSignal,QBasicTimer
from PyQt5.QtGui import QPainter, QColor, QFont,QPen
import json
class config:
	WIDTH=20#地图列数
	HEIGHT=20#地图行数
	blockLength=30#绘制画面时每一个节点方块的边长
class point:#点类(每一个唯一坐标只有对应的一个实例)
	_list=[]#储存所有的point类实例
	_tag=True#标记最新创建的实例是否为_list中的已有的实例,True表示不是已有实例
	def __new__(cls,x,y):#重写new方法实现对于同样的坐标只有唯一的一个实例
		for i in point._list:
			if i.x==x and i.y==y:
				point._tag=False
				return i
		nt=super(point,cls).__new__(cls)
		point._list.append(nt)
		return nt
	def __init__(self,x,y):
		if point._tag:
			self.x=x
			self.y=y
			self.father=None
			self.F=0#当前点的评分  F=G+H
			self.G=0#起点到当前节点所花费的消耗
			self.cost=0#父节点到此节点的消耗
		else:
			point._tag=True
	@classmethod
	def clear(cls):#clear方法,每次搜索结束后,将所有点数据清除,以便进行下一次搜索的时候点数据不会冲突。
		point._list=[]
	def __eq__(self,T):#重写==运算以便实现point类的in运算
		if type(self)==type(T):
			return (self.x,self.y)==(T.x,T.y)
		else:
			return False
	def __str__(self):
		return'(%d,%d)[F=%d,G=%d,cost=%d][father:(%s)]'%(self.x,self.y,self.F,self.G,self.cost,str((self.father.x,self.father.y)) if self.father!=None else 'null')
class A_Search:#核心部分,寻路类
	def __init__(self,arg_start,arg_end,arg_map):
		self.start=arg_start#储存此次搜索的开始点
		self.end=arg_end#储存此次搜索的目的点
		self.Map=arg_map#一个二维数组,为此次搜索的地图引用
		self.open=[]#开放列表:储存即将被搜索的节点
		self.close=[]#关闭列表:储存已经搜索过的节点
		self.result=[]#当计算完成后,将最终得到的路径写入到此属性中
		self.count=0#记录此次搜索所搜索过的节点数
		self.useTime=0#记录此次搜索花费的时间--在此演示中无意义,因为process方法变成了一个逐步处理的生成器,统计时间无意义。
		#开始进行初始数据处理
		self.open.append(arg_start)
	def cal_F(self,loc):
		print('计算值:',loc)
		G=loc.father.G+loc.cost
		H=self.getEstimate(loc)
		F=G+H
		print("F=%d G=%d H=%d"%(F,G,H))
		return {'G':G,'H':H,'F':F}
	def F_Min(self):#搜索open列表中F值最小的点并将其返回,同时判断open列表是否为空,为空则代表搜索失败
		if len(self.open)<=0:
			return None
		t=self.open[0]
		for i in self.open:
			if i.F<t.F:
				t=i
		return t
	def getAroundPoint(self,loc):#获取指定点周围所有可通行的点,并将其对应的移动消耗进行赋值。
		l=[(loc.x,loc.y+1,10),(loc.x+1,loc.y+1,14),(loc.x+1,loc.y,10),(loc.x+1,loc.y-1,14),(loc.x,loc.y-1,10),(loc.x-1,loc.y-1,14),(loc.x-1,loc.y,10),(loc.x-1,loc.y+1,14)]
		for i in l[::-1]:
			if i[0]<0 or i[0]>=config.HEIGHT or i[1]<0 or i[1]>=config.WIDTH:
				l.remove(i)
		nl=[]
		for i in l:
			if self.Map[i[0]][i[1]]==0:
				nt=point(i[0],i[1])
				nt.cost=i[2]
				nl.append(nt)
		return nl

	def addToOpen(self,l,father):#此次判断的点周围的可通行点加入到open列表中,如此点已经在open列表中则对其进行判断,如果此次路径得到的F值较之之前的F值更小,则将其父节点更新为此次判断的点,同时更新F、G值。
		for i in l:
			if i not in self.open:
				if i not in self.close:
					i.father=father
					self.open.append(i)
					r=self.cal_F(i)
					i.G=r['G']
					i.F=r['F']
			else:
				tf=i.father
				i.father=father
				r=self.cal_F(i)
				if i.F>r['F']:
					i.G=r['G']
					i.F=r['F']
					# i.father=father
				else:
					i.father=tf
	def getEstimate(self,loc):#H :从点loc移动到终点的预估花费
		return (abs(loc.x-self.end.x)+abs(loc.y-self.end.y))*10
	def DisplayPath(self):#在此演示中无意义
		print('搜索花费的时间:%.2fs.迭代次数%d,路径长度:%d'%(self.useTime,self.count,len(self.result)))
		if self.result!=None:
			for i in self.result:
				self.Map[i.x][i.y]=8
			for i in self.Map:
				for j in i:
					if j==0:
						print('%s'%'□',end='')
					elif j==1:
						print('%s'%'▽',end='')
					elif j==8:
						print('%s'%'★',end='')
				print('')
		else:
			print('搜索失败,无可通行路径')
	def process(self):#使用yield将process方法变成一个生成器,可以逐步的对搜索过程进行处理并返回关键数据
		while True:
			self.count+=1
			tar=self.F_Min()#先获取open列表中F值最低的点tar
			if tar==None:
				self.result=None
				self.count=-1
				break
			else:
				aroundP=self.getAroundPoint(tar)#获取tar周围的可用点列表aroundP
				self.addToOpen(aroundP,tar)#把aroundP加入到open列表中并更新F值以及设定父节点
				self.open.remove(tar)#将tar从open列表中移除
				self.close.append(tar)#已经迭代过的节点tar放入close列表中
				if self.end in self.open:#判断终点是否已经处于open列表中
					e=self.end
					self.result.append(e)
					while True:
						e=e.father
						if e==None:
							break
						self.result.append(e)
					yield (tar,self.open,self.close)
					break

			# self.repaint()
			# print('返回')
			yield (tar,self.open,self.close)
			time.sleep(5)#暂停
		self.useTime=time2-time1
class GameBoard(QMainWindow):#可视化类,pyqt5进行编写。
	def __init__(self):
		print('初始化地图...')
		self.Map=[]
		for i in range(config.HEIGHT):
			col=[]
			for j in range(config.WIDTH):
				col.append(0)
			self.Map.append(col)
		self.startPoint=None
		self.endPoint=None
		self.search=None
		self.centerTimer=None
		self.yi=None
		self.special=None
		self.displayFlush=False
		super().__init__()
		print('初始化UI...')
		self.initUI()
	def initUI(self):
		#开始初始化UI部分
			#创建UI控件
		self.label_tips=QLabel("<p style='color:green'>使用说明:</p>右键单击格子选定起始点,左键格子选定格子为墙壁或删除墙壁。\n<p style='color:green'>颜色说明:</p>\n黄色代表起点,绿色代表终点,黑色代表墙壁,红色代表待搜索的open列表,灰色代表已搜索过的close列表,蓝色代表当前搜索到的路径",self)
		self.label_display=QLabel("",self)
		self.button_start=QPushButton("开始搜索",self)
		self.button_clearSE=QPushButton("重选起始点",self)
		self.button_clearWall=QPushButton("清空地图墙壁",self)
		self.button_saveMap=QPushButton("保存地图",self)
		self.button_loadMap=QPushButton("加载地图",self)


			#设置控件属性
		self.label_tips.setWordWrap(True)
		self.label_display.setWordWrap(True)
			#设置控件样式
		self.label_display.setStyleSheet("border:1px solid black")
		self.label_display.setAlignment(Qt.AlignLeft)
		self.label_display.setAlignment(Qt.AlignTop)
			#设置控件的尺寸和位置
		self.label_tips.resize(200,150)
		self.button_saveMap.resize(80,30)
		self.button_loadMap.resize(80,30)
		self.label_display.resize(200,300)

		self.label_tips.move(100+(config.WIDTH-1)*config.blockLength,0)
		self.label_display.move(100+(config.WIDTH-1)*config.blockLength,400)
		self.button_start.move(100+(config.WIDTH-1)*config.blockLength,200)
		self.button_clearSE.move(100+(config.WIDTH-1)*config.blockLength,250)
		self.button_clearWall.move(100+(config.WIDTH-1)*config.blockLength,300)
		self.button_saveMap.move(100+(config.WIDTH-1)*config.blockLength,350)
		self.button_loadMap.move(200+(config.WIDTH-1)*config.blockLength,350)
			#给控件绑定事件
		self.button_start.clicked.connect(self.button_StartEvent)
		self.button_clearSE.clicked.connect(self.button_Clear)
		self.button_clearWall.clicked.connect(self.button_Clear)
		self.button_saveMap.clicked.connect(self.button_SaveMap)
		self.button_loadMap.clicked.connect(self.button_LoadMap)
		#UI初始化完成
		self.setGeometry(0, 0, 150+(config.WIDTH*config.blockLength-config.blockLength)+200, 150+(config.HEIGHT*config.blockLength-config.blockLength))
		self.setMinimumSize(150+(config.WIDTH*config.blockLength-config.blockLength)+200, 150+(config.HEIGHT*config.blockLength-config.blockLength))
		self.setMaximumSize(150+(config.WIDTH*config.blockLength-config.blockLength)+200, 150+(config.HEIGHT*config.blockLength-config.blockLength))
		self.setWindowTitle('A*搜索')
		self.show()
	def addDisplayText(self,text):
		if self.displayFlush:
			self.label_display.setText(text+'\n')
			self.displayFlush=False
		else:
			self.label_display.setText(self.label_display.text()+text+'\n')
	def mousePressEvent(self,event):
		x,y=event.x()-50,event.y()-50
		x=x//config.blockLength
		y=y//config.blockLength
		if x>=0 and x<config.WIDTH and y>=0 and y<config.HEIGHT:
			if event.button()==Qt.LeftButton:
				if (x,y)!=self.startPoint and (x,y)!=self.endPoint:
					self.Map[y][x]=(1 if self.Map[y][x]==0 else 0)
			if event.button()==Qt.RightButton:
				if self.Map[y][x]==0:
					if self.startPoint==None:
						self.startPoint=(x,y)
						self.addDisplayText('添加了一个起点:(%d,%d)'%(x,y))
					elif self.endPoint==None and self.startPoint!=(x,y):
						self.endPoint=(x,y)
						self.addDisplayText('添加了一个终点:(%d,%d)'%(x,y))
			self.repaint()
	def button_StartEvent(self):
		sender=self.sender()
		print(sender)
		if self.startPoint!=None and self.endPoint!=None:
			if self.centerTimer==None:
				self.centerTimer=QBasicTimer()
			self.button_start.setEnabled(False)
			self.button_clearSE.setEnabled(False)
			self.button_clearWall.setEnabled(False)
			self.centerTimer.start(200,self)
			self.search=A_Search(point(self.startPoint[1],self.startPoint[0]),point(self.endPoint[1],self.endPoint[0]),self.Map)
			self.yi=self.search.process()
			self.addDisplayText('开始进行搜索')
	def button_SaveMap(self):
		with open('map.txt','w') as f:
			f.write(json.dumps(self.Map))
			self.addDisplayText('地图保存成功-->map.txt')
		# else:
			# self.addDisplayText('地图保存失败')
	def button_LoadMap(self):
		try:
			with open('map.txt','r') as f:
				self.Map=json.loads(f.read())
				config.HEIGHT=len(self.Map)
				config.WIDTH=len(self.Map[0])
				self.addDisplayText('地图加载成功')
				self.repaint()
		except Exception as e:
			print('失败',e,type(e))
			if type(e)==FileNotFoundError:
				self.addDisplayText('地图加载失败:地图文件不存在')
			elif type(e)==json.decoder.JSONDecodeError:
				self.addDisplayText('地图加载失败:错误的地图文件')
	def button_Clear(self):
		sender=self.sender()
		print(self.button_clearSE,type(self.button_clearSE))
		if sender==self.button_clearSE:
			self.startPoint=None
			self.endPoint=None
			self.repaint()
			self.addDisplayText('清空起始点')
		elif sender==self.button_clearWall:
			for i in range(len(self.Map)):
				for j in range(len(self.Map[i])):
					self.Map[i][j]=0
			self.repaint()
			self.addDisplayText('清空所有墙壁')
	def paintEvent(self, event):
		qp = QPainter()
		qp.begin(self)
		self.drawBoard(event,qp)
		qp.end()
	def drawBoard(self, event, qp):
	    self.drawMap(qp)
	def drawMap(self,qp):#画面绘制方法,每次地图有所改动都将重绘
		time1=time.time()
		if self.search!=None:
			if self.special!=None:
				e=self.special[0]
				path=[e]
				while True:
					e=e.father
					if e!=None:
						path.append(e)
					else:
						break
			else:
				path=None
			pen=QPen(QColor(0,0,0),1,Qt.SolidLine)
			qp.setPen(pen)
			for i in range(len(self.Map)):
				for j in range(len(self.Map[i])):
					wordTag=False
					if i==self.search.start.x and j==self.search.start.y:
						qp.setBrush(QColor(255,255,0))
					elif i==self.search.end.x and j==self.search.end.y:
						qp.setBrush(QColor(100,200,50))
					else:
						if self.Map[i][j]==0:
							tagx=True
							if path:
								for k in path:
									if k.x==i and k.y==j:
										tagx=False
										qp.setBrush(QColor(0,100,255))
							if tagx:
								if self.special!=None:
									if i==self.special[0].x and j==self.special[0].y:
										qp.setBrush(QColor(0,255,0))
									else:
										tag=True
										for k in self.special[1]:
											if k.x==i and k.y==j:
												tag=False
												wordTag=True
												word=str(k.F)

												qp.setBrush(QColor(150,0,0))
												break
											else:
												qp.setBrush(QColor(220,220,220))
										if tag:
											for k in self.special[2]:
												if k.x==i and k.y==j:
													qp.setBrush(QColor(150,150,150))
													break
												else:
													qp.setBrush(QColor(220,220,220))
								else:
									qp.setBrush(QColor(220,220,220))
						elif self.Map[i][j]==1:
							qp.setBrush(QColor(0,0,0))
						else:
							qp.setBrush(QColor(255,0,0))
					qp.drawRect(50+j*config.blockLength,50+i*config.blockLength,config.blockLength,config.blockLength)
					if wordTag:
						qp.setFont(QFont('楷体',5,QFont.Light))
						qp.drawText(50+10+j*config.blockLength,50+10+i*config.blockLength,word)
						wordTag=False
		#time.sleep(20)
		else:
			for i in range(len(self.Map)):
				for j in range(len(self.Map[i])):
					if (j,i)==self.startPoint:
						qp.setBrush(QColor(255,255,0))
					elif (j,i)==self.endPoint:
						qp.setBrush(QColor(100,200,50))
					else:
						if self.Map[i][j]==0:
							qp.setBrush(QColor(220,220,220))
						elif self.Map[i][j]==1:
							qp.setBrush(QColor(0,0,0))
						else:
							qp.setBrush(QColor(255,0,0))

					qp.drawRect(50+j*config.blockLength,50+i*config.blockLength,config.blockLength,config.blockLength)
		time2=time.time()
	#time.sleep(20)
		# print('绘制时间:',time2-time1)
	def timerEvent(self,e):
		try:
			data=next(self.yi)
		except Exception as e:
			self.addDisplayText('搜索结束:')
			print('搜索结束!')
			if self.search.result==None:
				self.addDisplayText('未找到可行路径')
				print('搜索结束!')
			else:
				self.addDisplayText('总计搜索节点数:%d'%self.search.count)
				self.addDisplayText('最终路径长度:%d'%len(self.search.result))
			self.centerTimer.stop()
			self.search=None
			self.yi=None
			self.special=None
			point.clear()
			self.button_start.setEnabled(True)
			self.button_clearSE.setEnabled(True)
			self.button_clearWall.setEnabled(True)
			self.displayFlush=True
		else:
			self.special=data
			self.repaint()
if __name__ == '__main__':
	app = QApplication(sys.argv)
	ex = GameBoard()
	sys.exit(app.exec_())

注意:代码运行可以设置动态遍历的时候暂停时间(大概在145行的time.sleep(5)语句)

运行结果 

输出每次计算的每个点的F和父结点,直接看图吧!

详细列表

初始化地图...
初始化UI...
<PyQt5.QtWidgets.QPushButton object at 0x0000017CC699AC18>
计算值: (2,3)[F=0,G=0,cost=10][father:((2, 2))]
F=40 G=10 H=30
计算值: (3,3)[F=0,G=0,cost=14][father:((2, 2))]
F=54 G=14 H=40
计算值: (3,2)[F=0,G=0,cost=10][father:((2, 2))]
F=60 G=10 H=50
计算值: (3,1)[F=0,G=0,cost=14][father:((2, 2))]
F=74 G=14 H=60
计算值: (2,1)[F=0,G=0,cost=10][father:((2, 2))]
F=60 G=10 H=50
计算值: (1,1)[F=0,G=0,cost=14][father:((2, 2))]
F=74 G=14 H=60
计算值: (1,2)[F=0,G=0,cost=10][father:((2, 2))]
F=60 G=10 H=50
计算值: (1,3)[F=0,G=0,cost=14][father:((2, 2))]
F=54 G=14 H=40
计算值: (3,3)[F=54,G=14,cost=10][father:((2, 3))]
F=60 G=20 H=40
计算值: (3,2)[F=60,G=10,cost=14][father:((2, 3))]
F=74 G=24 H=50
计算值: (1,2)[F=60,G=10,cost=14][father:((2, 3))]
F=74 G=24 H=50
计算值: (1,3)[F=54,G=14,cost=10][father:((2, 3))]
F=60 G=20 H=40
计算值: (4,4)[F=0,G=0,cost=14][father:((3, 3))]
F=68 G=28 H=40
计算值: (4,3)[F=0,G=0,cost=10][father:((3, 3))]
F=74 G=24 H=50
计算值: (4,2)[F=0,G=0,cost=14][father:((3, 3))]
F=88 G=28 H=60
计算值: (3,2)[F=60,G=10,cost=10][father:((3, 3))]
F=74 G=24 H=50
计算值: (1,2)[F=60,G=10,cost=10][father:((1, 3))]
F=74 G=24 H=50
计算值: (0,2)[F=0,G=0,cost=14][father:((1, 3))]
F=88 G=28 H=60
计算值: (0,3)[F=0,G=0,cost=10][father:((1, 3))]
F=74 G=24 H=50
计算值: (0,4)[F=0,G=0,cost=14][father:((1, 3))]
F=68 G=28 H=40
计算值: (4,3)[F=74,G=24,cost=14][father:((3, 2))]
F=74 G=24 H=50
计算值: (4,2)[F=88,G=28,cost=10][father:((3, 2))]
F=80 G=20 H=60
计算值: (4,1)[F=0,G=0,cost=14][father:((3, 2))]
F=94 G=24 H=70
计算值: (3,1)[F=74,G=14,cost=10][father:((3, 2))]
F=80 G=20 H=60
计算值: (2,1)[F=60,G=10,cost=14][father:((3, 2))]
F=74 G=24 H=50
计算值: (3,1)[F=74,G=14,cost=10][father:((2, 1))]
F=80 G=20 H=60
计算值: (3,0)[F=0,G=0,cost=14][father:((2, 1))]
F=94 G=24 H=70
计算值: (2,0)[F=0,G=0,cost=10][father:((2, 1))]
F=80 G=20 H=60
计算值: (1,0)[F=0,G=0,cost=14][father:((2, 1))]
F=94 G=24 H=70
计算值: (1,1)[F=74,G=14,cost=10][father:((2, 1))]
F=80 G=20 H=60
计算值: (1,2)[F=60,G=10,cost=14][father:((2, 1))]
F=74 G=24 H=50
计算值: (1,1)[F=74,G=14,cost=10][father:((1, 2))]
F=80 G=20 H=60
计算值: (0,1)[F=0,G=0,cost=14][father:((1, 2))]
F=94 G=24 H=70
计算值: (0,2)[F=88,G=28,cost=10][father:((1, 2))]
F=80 G=20 H=60
计算值: (0,3)[F=74,G=24,cost=14][father:((1, 2))]
F=74 G=24 H=50
计算值: (4,5)[F=0,G=0,cost=10][father:((4, 4))]
F=68 G=38 H=30
计算值: (5,5)[F=0,G=0,cost=14][father:((4, 4))]
F=82 G=42 H=40
计算值: (5,4)[F=0,G=0,cost=10][father:((4, 4))]
F=88 G=38 H=50
计算值: (5,3)[F=0,G=0,cost=14][father:((4, 4))]
F=102 G=42 H=60
计算值: (4,3)[F=74,G=24,cost=10][father:((4, 4))]
F=88 G=38 H=50
计算值: (3,5)[F=0,G=0,cost=14][father:((4, 4))]
F=62 G=42 H=20
计算值: (3,6)[F=0,G=0,cost=10][father:((3, 5))]
F=62 G=52 H=10
计算值: (4,6)[F=0,G=0,cost=14][father:((3, 5))]
F=76 G=56 H=20
计算值: (4,5)[F=68,G=38,cost=10][father:((3, 5))]
F=82 G=52 H=30
计算值: (2,5)[F=0,G=0,cost=10][father:((3, 5))]
F=62 G=52 H=10
计算值: (2,6)[F=0,G=0,cost=14][father:((3, 5))]
F=56 G=56 H=0
搜索结束!

可执行文件

已经将程序打包成exe可执行文件,点击即可用,不需要py环境。

链接:https://pan.baidu.com/s/1UqvI5vtoxwXu0PPUFHfxdg 
提取码:fwwm 
复制这段内容后打开百度网盘手机App,操作更方便哦

拓展

Dijkstra算法和A*算法的比较

Dijkstra算法和A*都是最短路径问题的常用算法,下面就对这两种算法的特点进行一下比较。
1.Dijkstra算法计算源点到其他所有点的最短路径长度,A*关注点到点的最短路径(包括具体路径)。
2.Dijkstra算法建立在较为抽象的图论层面,A*算法可以更轻松地用在诸如游戏地图寻路中。
3.Dijkstra算法的实质是广度优先搜索,是一种发散式的搜索,所以空间复杂度和时间复杂度都比较高。对路径上的当前点,A*算法不但记录其到源点的代价,还计算当前点到目标点的期望代价,是一种启发式算法,也可以认为是一种深度优先的算法。
4.由第一点,当目标点很多时,A*算法会带入大量重复数据和复杂的估价函数,所以如果不要求获得具体路径而只比较路径长度时,Dijkstra算法会成为更好的选择。

参考: https://blog.csdn.net/weixin_42382758/article/details/88840581

路径规划A*算法
03-21
用A*算法实现路径规划, A*算法是很经典的只能启发式搜索算法,本程序用Visual C++实现。
A*算法讲解PPT(A算法
05-30
A*算法讲解PPT(A算法)偏向轻松风格,可自己修改,并有演示视频
A*(A-star)算法 定义+特性+原理+公式+Python示例代码(带详细注释)
最新发布
qq_51929160的博客
04-14 2886
A* 算法是一种高效的路径寻找算法,它通过结合启发式评估和实际成本来找到从起点到终点的最短路径。该算法评估每个节点的成本函数,它由两部分组成:一部分是从起点到当前节点的实际路径成本(G值),另一部分是当前节点到目标的预估成本(H值)。通过这种方式,A* 算法能够避免不必要的搜索,从而优化了路径搜索过程。该算法不仅应用于计算机科学领域的图搜索,还广泛用于游戏设计、机器人导航、地图定位等多个实际应用中,因其高效和可靠而受到推崇。
A*算法学习(python代码实现)
05-17
A*算法是路径规划的算法之一,也是最经典的算法。此代码为学习过程中用python编写,能够实现生成指定大小的地图,并随机生成地图上的障碍物,然后在地图上进行算法寻最优路径
A星(A*、A Star)路径规划算法详解(附MATLAB代码)
热门推荐
晨少的博客
06-27 3万+
一、A* 算法原理 二、A* 算法实现步骤 三、A* 算法MATLAB代码举个例子来说,A*算法通常要将地图网格化,如下图所示: 假设有一只乌龟在追小白兔,乌龟此时的位置是(2,2),小白兔的位置是(6,6),假设小白兔静止不动。 根据A *算法的原理,乌龟只能向左、向右、向上、向下走,那么(1,2)、(2,1)、(3,2)、(2,3)是乌龟下一轮可以到达的点,这些点叫做 待探索的点步骤一 寻找下一步可以到达的节点,将这些待探索的点加入待探索数组 frontier 中,也叫边界数组。 计算出新加入点的代价
A*算法 matlab版
11-21
A*算法,动态路径规划算法的一种,程序直接放到matlab即可运行。
人工智能实验A*算法例子
04-10
利用A星算法解决Robot问题(下面有介绍)。 Robot问题:从起点到终点需要的最短步骤,其中包括障碍物,移动方向(东西南北),每次只能转向90度或者向前走一步
A*算法
10-15 5893
如此好贴,不能不转!原文地址:http://dev.gameres.com/Program/Abstract/Arithmetic/AmitAStar.mht 本文版权归原作者、译者所有,我只是转贴;如果侵害到您的权益,请联系我,我将删除本文。 基本上,这文章可以说是最佳A*
一、A*搜索算法
dinongxu8804的博客
12-23 1236
经典算法研究系列:一、A*搜索算法 作者:July、二零一一年一月----------------------------------博主说明:1、本经典算法研究系列,此系列文章写的不够好之处,还望见谅。2、本经典算法研究系列,系我参考资料,一篇一篇原创所作,转载必须注明作者本人July及出处。3、本经典算法研究系列...
a*算法流程图(只是流程图)
12-19
a*算法流程图(只是流程图)A*算法是一种在静态路网中求解最短路径最有效的直接搜索方法,也是解决许多其他搜索问题的有效算法算法中的距离估算值与实际值越接近,扩展的节点数越少, 搜索速度越快。
A* 算法(示例程序+源码)(C#版)
05-30
这是一再游戏中很著名的寻路算法,是基于曼哈顿的算法的A*算法
非常完整的A*算法具体实例代码
11-17
这是A*算法的最短路径搜索代码,代码完整,可以直接打开运行,也可以直接拷贝到需要用的项目中。 注释非常详细,小白一看就能懂,附带伪代码 一步步看 大家多多学习又不明白可以联系
A*算法实例
03-17
此实例将A*算法的搜索过程描述出来,可以明显的看出搜索路径,用游戏实例的方法表示出来该算法,有助于理解
A*算法实现及讲解
09-13
这里用的是经典的A*算法实现的路径最优寻找
移动机器人路径规划 几种A*算法改进matlab实现
12-05
移动机器人路径规划 几种A*算法改进matlab实现,可直接运行。适用于初学者基于A*算法进行改进,容易理解并上手,
A* 算法详解(超级详细讲解附有大图)
aliyonghang的博客
01-01 1万+
今天想跟大家聊的,是我们经常用到,但是却让大家觉得十分神秘的那个算法:A*。这是一个远古而又非常经典的游戏——红警和玩的时候,就会发现这里面的兵,你只要指定好地点,他们就会自己朝目的地进发,最终去向你指定的地点。。。(这段是看了参考资料【1】之后乱编出来的)很多游戏也是这样,它会将你指定的人物,以一定的路径,到达某地(逐渐抽象)。简单来说,就是。在游戏,乃至生活之中,在很多地方会有寻路的需求。而我们因为各种原因,总会寻求最短的路线,在计算机科学中,这种寻求最短路径的问题统称为。
举例详细说明A算法和A*算法的区别
06-10
A算法和A*算法都是常用的路径规划算法,它们的区别在于A*算法在搜索过程中利用了启发式函数来减少搜索的节点数,从而提高了搜索效率。 具体来说,A算法是一种基于贪心策略的搜索算法,它通过估算每个节点到目标点的距离来选择下一个扩展的节点。但是,A算法没有考虑到每个节点到起点的距离,因此可能会出现在已经扩展了很多节点之后发现更优的路径的情况,导致搜索效率较低。 而A*算法则是在A算法的基础上加入了启发式函数的思想,它综合了每个节点到起点和到目标点的距离估算值,从而可以更加准确地评估每个节点的优先级。在搜索过程中,A*算法会优先选择那些估价函数值最小的节点进行扩展,从而可以尽可能地减少搜索的节点数,提高搜索效率。 因此,相比较而言,A*算法更适合用于路径规划问题,尤其是在处理大规模地图时,可以大大减少搜索时间,提高搜索效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • c语言一些简单的程序 170252
  • A*算法(超级详细讲解,附有举例的详细手写步骤) 121397
  • 11 fi 60991
  • (树莓派)解决问题:AssertionError: Torch not compiled with CUDA enabled 55459
  • 将图片转化为.py文件 53578

分类专栏

  • 论文阅读 29篇
  • 前端 3篇
  • 旋转论文阅读 18篇
  • 树莓派 22篇
  • 项目 2篇
  • 记录
  • 代码 9篇
  • 填坑 36篇
  • 传感器 3篇
  • 小目标 1篇
  • pytorch 3篇
  • # 机器学习 32篇
  • openvino
  • 人工智能杂七杂八 111篇
  • 吴恩达深度学习笔记 16篇
  • 动手深度学习 38篇
  • 基本操作 14篇
  • 计算机视觉函数库入门含oepncv 43篇
  • 计算机视觉基础图片处理 42篇
  • 计算机基础 70篇
  • 计算机网络 18篇
  • python学习 26篇
  • Qt 11篇
  • 算法入门 97篇
  • 算法之进制转换 8篇
  • STL 8篇
  • 算法之排序 8篇
  • 算法之递归 3篇
  • 算法之贪心 1篇
  • 算法之动态规划 3篇
  • 算法之DFS 3篇
  • 算法之BFS 2篇
  • 算法之克鲁斯卡尔 2篇
  • 算法之并查集 8篇
  • 算法之背包 7篇
  • 算法之数论 4篇

最新评论

  • A*算法(超级详细讲解,附有举例的详细手写步骤)

    m0_49623520: ppt感觉前后矛盾,不是说每次在当前节点的周围节点选择最小的F吗?为什么a8选完后又跑到了a3

  • A*算法(超级详细讲解,附有举例的详细手写步骤)

    秋风依旧658: 博主,请问里面的process方法中,yield (tar, self.open, self.close)作用是什么

  • A*算法(超级详细讲解,附有举例的详细手写步骤)

    秋风依旧658: 里面有一个time.sleep(5),你删掉就变快了

  • 【论文阅读】Oriented R-CNN for Object Detection

    weixin_59137013: 本文判断正负样本时,用的水平锚框吗

  • 有关摔倒检测数据集(fall detection databases)

    大熊猫真可爱: 这个acc的,怎么成6列呢

大家在看

  • Java中的集合框架 862

最新文章

  • 【C++】JZ3 数组中重复的数字(数组与矩阵)
  • 【最长公共子序列】两行字符串,不交叉相连,最多连线
  • 【vue】v-for中动态加载图片,图片路径拼接问题
2022年74篇
2021年190篇
2020年378篇
2018年62篇

目录

目录

评论 84
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clark-dj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值

深圳SEO优化公司荷坳百搜标王推荐吉林模板推广推荐玉树网站建设滨州阿里店铺托管多少钱保山品牌网站设计公司海东网站制作多少钱铜川品牌网站设计公司淮南网页制作报价佛山网页制作报价马鞍山百度爱采购价格咸宁外贸网站设计价格忻州优化报价荆门网络推广推荐黄山品牌网站设计报价商洛网站优化软件哪家好徐州外贸网站制作成都推广网站价格无锡百度标王推荐扬州高端网站设计报价汕头百搜标王价格文山网站建设推荐宁德百度网站优化报价诸城阿里店铺托管公司龙岗SEO按天收费公司湘西SEO按天计费报价成都网站制作设计推荐桐城关键词按天扣费推荐铁岭百度网站优化排名公司保山网络推广公司亳州网站seo优化报价歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化