游戏中的AI---寻路算法A* [1](上篇 Dijkstra算法铺垫)

本文深入探讨了A*算法的原理与应用,通过对比Dijkstra算法,详细解析了A*算法如何高效解决寻路问题。文章通过实例图解算法流程,并提供了C++代码实现,适合初学者和开发者参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0.简介

网上A*算法介绍已经很多很多了,不过我作为学习和实现,我还会把我的经历记录下来。

1.算法简介

A*算法,听到这个算法后,很难直接判断出这个算法是解决什么问题,这是解决寻路问题的,为什么叫A*?,据考证,最早是有A1,A2算法,后来发展了更优秀的算法就叫A*了,应该和B语言,C语言,C++的叫法类似吧。

2.算法详细介绍

现在进入正题,学习A*算法之前就先理解 一些迪杰斯特拉最短路径算法,首先简述一下Dijkstra算法流程。文字不太好叙述,画图的话用软件画比较不方便,所以我采用手画图,方便快捷。

图1 例子图1

图1是例举的一个图。

在往下继续前,思考一个问题,假如从A点开始,那么找到与A连接的最短的边e,这条边另外一头与某点X相连,那么e是不是X到A的最短路径,答案:是。因为我们无法找到不走e并且还比e更短的路径了(没有负权值),因为此时e就是让X到A最短的路径。在知道了这个前提之后,我们将这个理论简单命名为理论S,方便后面叙述,继续往下看。

图2 例子图2

图2中少了一点,就是刚刚的点B,这里将之前的点B删除了,因为B是与A连接最近的点,看作是边的一部分,这样一来,A到D就相当于路径为长度2的一条边了。因为这个算法是计算从A出发到其余所有点的最短距离,所以我们只需要关注A到任一点X的距离,现在看图2与A直接相连的边最短的是哪条,有两条,这里就选择A-D这条吧,随意选的。再根据理论S所描述的,此时D到A的最短距离我们得到了,是2。

图3 例子图3

这回将点D看作是边的一部分,就是如图3的效果,根据前面的方法,继续进行,下一个最短的边是到C点的,然后是E,F,就这样找到了A到所有点的最短距离。

3.算法实现

class GEdge
{
public:
	int begin, end;
	double cost;
	GEdge() {}
	GEdge(int _begin,int _end,double _cost):begin(_begin),end(_end),cost(_cost){}
	GEdge(int _begin, int _end) :begin(_begin), end(_end), cost(1.0) {}

};
class GNode
{
public:
	int id;
	GNode(int _id) : id(_id) {}
	GNode(){}
	list<GEdge>edges;
};
class SelectNode
{
public:
	int id;
	double cost;
	SelectNode() {}
	SelectNode(int _id,double _cost) : id(_id),cost(_cost){}
	bool operator<(const SelectNode& a) const
	{
		return cost > a.cost; 
	}
};

int main()
{
    
   	//邻接表 每次输入的是 起点 终点 权值
	unordered_map<int, GNode> nodes;
	for (int i = 0; i < 12; i++)
	{
		int s, e;
		double c;
		cin >> s >> e>>c;
		if (nodes.find(s) == nodes.end())
		{
			nodes[s] = GNode(s);
			nodes[s].edges.push_back(GEdge(s,e,c));
		}
		else
		{
			nodes[s].edges.push_back(GEdge(s,e,c));
		}
	}
	//优先级队列,每次获取最短边
	priority_queue<SelectNode> queue;
	double length[7] = {0};
	//获取初始点
	int start = 1;
	queue.push(SelectNode(1, 0));
	while (!queue.empty())
	{
		SelectNode nodeInfo = queue.top();
		queue.pop();
		for (auto edge : nodes[nodeInfo.id].edges)
		{
			//如果比原来的路径小就加入队列中
			if (length[edge.end]==0 ||length[edge.begin] + edge.cost < length[edge.end])
			{
				length[edge.end] = edge.cost + length[edge.begin];
				queue.push(SelectNode(edge.end, length[edge.end]));
			}
		}
	}
	length[start] = 0;
	for (int i = 1; i < 7; i++)
	{
		cout << length[i] << " ";
	}


	return 0;
}

测试数据

1 2 1
2 1 1
1 3 2
3 1 2
2 4 1
4 2 1
3 4 3
4 3 3
4 5 3
5 4 3
4 6 4
6 4 4

代码简单说一下,用STL是unorderd_map和list组合成邻接表,然后用一个数组维持最短路径。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值