一个小笔记(5):A*算法

A-Star算法是一种静态路网中求解最短路径最有效的直接搜索方法
其实百科有

http://baike.baidu.com/link?url=CvmkWQIAmztYgMq3Nk1WyWkDiC0koVQALKzE4wBF4CWbYBtT19iWMBdSht9LBf7ZjUnA509U-JGWvxDYBk5LCq

?

咳咳,直接上代码。各种注释也算是有助理解了,毕竟这还是抄的~

?

// A*寻路算法.cpp : 定义控制台应用程序的入口点。

// Win32控制台程序

#include
<math.h>

#include
<list>

?

using
namespace
std;

?

/*

把地图当成一个个的格子

公式:F=G+H

F:相对路径长度

G:从起点沿着产生的路径,移动到指定点的耗费(路径长度)

H:预估值,从指定的格子移动到终点格子的预计耗费

使用两个表来保存相关数据

启动列表:有可能将要经过的点存到启动列表

关闭列表:不会再被遍历的点

?

步骤

1、将起点格子加入启动列表中

2、在启动列表中查找权值(F值)最小的格子

3、查找它周围的能走的格子

4、把这些格子加入启动列表中,已经在启动或关闭列表中的格子不用加入

5、把这些加入启动列表的格子的"父格子"设为当前格子

6、再把当前格子从启动列表中删除,加入关闭列表中

7、如果终点在启动列表中,则找到路径,退出流程,不进行第9步

8、如果启动列表中没有格子了,说明没有找到路径,退出流程,不进行第9步

9、跳转第2步

*/

?

// 0:可行走的点

// 1:阻挡点

// 2:路径

// 3:起点

// 4:终点

int
g_PathLattice[10][10] =

{

????{ 0,0,0,0,0,0,0,0,0,0 },

????{ 0,0,0,0,0,0,0,0,0,0 },

????{ 0,0,0,0,0,0,0,0,0,0 },

????{ 0,0,0,0,1,0,0,0,0,0 },

????{ 0,0,3,0,1,0,4,0,0,0 },

????{ 0,0,0,0,1,0,0,0,0,0 },

????{ 0,0,0,0,0,0,0,0,0,0 },

????{ 0,0,0,0,0,0,0,0,0,0 },

????{ 0,0,0,0,0,0,0,0,0,0 },

????{ 0,0,0,0,0,0,0,0,0,0 },

};

?

struct
Node

{

????int
row; // 行

????int
rank; // 列

????int
f;

????int
g;

????int
h;

????Node * pParent; // 当前结点路径的前一个结点(父格子)

};

?

#define
LatticeLen 10 // 格子边长

?

// 函数前向声明

int
Distance(int
row1, int
rank1, int
row2, int
rank2);

bool
IsNodeInList(Node * pNode, list<Node *> list);

Node * GetNearestNode(list<Node *> list, Node * Rec);

void
GetNearNodeList(Node * pNode, list<Node *> & listNear,

????list<Node *> listStart, list<Node *> listEnd, Node * pEndNode);

void
EraseFromList(Node * pNode, list<Node *> & listStart);

void
ClearList(list<Node *> nodeList);

?

int
main()

{

????// 起点

????int
rowStart;

????int
rankStart;

?

????// 终点

????int
rowEnd;

????int
rankEnd;

?

????// 查找起点和终点的位置

????for (int
i = 0; i < 10; i++)

????{

????????for (int
j = 0; j < 10; j++)

????????{

????????????if (g_PathLattice[i][j] == 3)

????????????{

????????????????rowStart = i;

????????????????rankStart = j;

????????????}

????????????if (g_PathLattice[i][j] == 4)

????????????{

????????????????rowEnd = i;

????????????????rankEnd = j;

????????????}

????????}

????}

?

????// 起点

????Node * nodeStart = new
Node;

????nodeStart->row = rowStart;

????nodeStart->rank = rankStart;

????nodeStart->g = 0;

????nodeStart->h = Distance(rowStart, rankStart, rowEnd, rankEnd);

????nodeStart->f = nodeStart->h;

????nodeStart->pParent = nullptr;

?

????// 终点

????Node * nodeEnd = new
Node;

????nodeEnd->row = rowEnd;

????nodeEnd->rank = rankEnd;

?

????// 定义启动列表和关闭列表

????list<Node *> listStart;

????list<Node *> listEnd;

?

????// 把起点加入启动列表

????listStart.push_back(nodeStart);

?

????// 当前结点

????Node * pNowNode = nullptr;

?

????// 如果终点在启动列表中,则已经找到路径,退出循环

????while (!IsNodeInList(nodeEnd, listStart))

????{

????????Node * Rec = nullptr;

????????// 查找权值最小的格子作为当前点

????????pNowNode = GetNearestNode(listStart, Rec);

?

????????// 如果没有找到,则说明没有路径

????????if (pNowNode == nullptr)

????????{

????????????break;

????????}

?

????????// 存放当前格子周围能加入启动列表的格子

????????list<Node *> listNear;

????????GetNearNodeList(pNowNode, listNear, listStart, listEnd, nodeEnd);

?

????????// 将当前结点加入关闭列表中

????????listEnd.push_back(pNowNode);

?

????????// 将当前结点从启动列表中删除

????????EraseFromList(pNowNode, listStart);

?

????????// 将周围点加入启动列表中

????????for (list<Node *>::iterator
it = listNear.begin();

????????????it
!=
listNear.end(); it++)

????????{

????????????listStart.push_back(*it);

????????}

????}

?

????if (pNowNode == nullptr)

????{

????????printf("路径不存在\n");

????????ClearList(listStart);

????????ClearList(listEnd);

????????delete
nodeEnd;

?

????????return 0;

????}

?

????// 在启动列表中找到终点

????Node * pNodeFind = nullptr;

????for (list<Node *>::iterator
it = listStart.begin();

????????it
!=
listStart.end(); it++)

????{

????????if ((*it)->row == nodeEnd->row &&

????????????(*it)->rank == nodeEnd->rank)

????????{

????????????pNodeFind = (*it);

????????????break;

????????}

????}

?

????while (pNodeFind)

????{

????????g_PathLattice[pNodeFind->row][pNodeFind->rank] = 2;

????????pNodeFind = pNodeFind->pParent;

????}

?

????for (int
i = 0; i < 10; i++)

????{

????????for (int
j = 0; j < 10; j++)

????????{

????????????if (g_PathLattice[i][j] == 0)

????????????{

????????????????printf("^ ");

????????????}

????????????else
if (g_PathLattice[i][j] == 1)

????????????{

????????????????printf("* ");

????????????}

????????????else
if (g_PathLattice[i][j] == 2)

????????????{

????????????????printf("# ");

????????????}

????????}

????????printf("\n");

????}

?

????ClearList(listStart);

????ClearList(listEnd);

?

????delete
nodeEnd;

?

????return 0;

}

?

int
Distance(int
row1, int
rank1, int
row2, int
rank2)

{

????// 格子的中点坐标

????int
x1 = rank1 * LatticeLen + LatticeLen / 2;

????int
y1 = row1 * LatticeLen + LatticeLen / 2;

????int
x2 = rank2 * LatticeLen + LatticeLen / 2;

????int
y2 = row2 * LatticeLen + LatticeLen / 2;

?

????return (int)sqrt((double)((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));

}

?

bool
IsNodeInList(Node * pNode, list<Node *> NodeList)

{

????for (list<Node *>::iterator
it = NodeList.begin();

????????it
!=
NodeList.end(); it++)

????{

????????if (pNode->row == (*it)->row && pNode->rank == (*it)->rank)

????????{

????????????return
true;

????????}

????}

?

????return
false;

}

?

Node * GetNearestNode(list<Node *> NodeList, Node * Rec)

{

????int
tempF = 1000000;

????for (list<Node *>::iterator
it = NodeList.begin();

????????it
!=
NodeList.end(); it++)

????{

????????if ((*it)->f < tempF)

????????{

????????????Rec = *it;

????????????tempF = (*it)->f;

????????}

????}

?

????return
Rec;

}

?

void
GetNearNodeList(Node * pNode, list<Node *> & listNear,

????list<Node *> listStart, list<Node *> listEnd, Node * pEndNode)

{

????// 将结点旁边的8个点加入到listNear中

????// 在启动或关闭列表中的点不能加入listNear

????// 阻挡点不能加入listNear

????for (int
i = -1; i <= 1; i++)

????{

????????for (int
j = -1; j <= 1; j++)

????????{

????????????if (i == 0 && j == 0)

????????????{

????????????????// 自己格子

????????????????continue;

????????????}

?

????????????int
rowTemp = pNode->row + i;

????????????int
rankTemp = pNode->rank + j;

?

????????????if (rowTemp < 0 || rankTemp < 0 || rowTemp > 9 || rankTemp > 9)

????????????{

????????????????// 越界

????????????????continue;

????????????}

?

????????????if (g_PathLattice[rowTemp][rankTemp] == 1)

????????????{

????????????????// 阻挡点

????????????????continue;

????????????}

?

????????????Node
node;

????????????node.row = rowTemp;

????????????node.rank = rankTemp;

????????????if (IsNodeInList(&node, listStart))

????????????{

????????????????// 在启动列表中

????????????????continue;

????????????}

????????????if (IsNodeInList(&node, listEnd))

????????????{

????????????????// 在关闭列表中

????????????????continue;

????????????}

?

????????????Node * pNearNode = new
Node;

????????????pNearNode->g = pNode->g + Distance(pNode->row, pNode->rank, rowTemp, rankTemp);

????????????pNearNode->h = Distance(rowTemp, rankTemp, pEndNode->row, pEndNode->rank);

????????????pNearNode->f = pNearNode->g + pNearNode->h;

????????????pNearNode->row = rowTemp;

????????????pNearNode->rank = rankTemp;

????????????pNearNode->pParent = pNode;

????????????listNear.push_back(pNearNode);

????????}

????}

}

?

void
EraseFromList(Node * pNode, list<Node *> & listStart)

{

????for (list<Node *>::iterator
it = listStart.begin();

????????it
!=
listStart.end(); it++)

????{

????????if (pNode->row == (*it)->row && pNode->rank == (*it)->rank)

????????{

????????????listStart.erase(it);

????????????return;

????????}

????}

}

?

void
ClearList(list<Node *> nodeList)

{

????for (list<Node *>::iterator
it = nodeList.begin();

????????it
!=
nodeList.end(); it++)

????{

????????delete
*it;

????}

}

?

?

?

?

时间: 2024-08-30 08:21:31

一个小笔记(5):A*算法的相关文章

一个小笔记(10):编译原理

这也是一个大笔记.

一个小笔记(9):文法

有时候,对于概念很难懂的东西,多打几遍应该就会懂了.这是一个大笔记.很可怕的笔记.很可怕... ?

一个小笔记(13):其它通用算法

一个小笔记(6):常见小疑问

Q1:前置++与后置++的疑问?int?q = 10;int a, b;a = q++;b = ++q; a的值为10,b的值为12 [a = q++]理解:先把q赋值给a,再把q自加1实质:赋值符号的优先级低于后置++的优先级,所以并不是把q赋值给a后再将q加1.q++相当于调用了一个函数,会返回一个值,之后再将q自加1,返回的值赋值给a[b = ++q]将q自加1之后赋值给b Q2:if(a + b > c) 和 if(c - a < b) 是否等价?不等价,可能出现溢出问题 int a

一个小笔记(3):约瑟夫环

什么是约瑟夫环?其实百度有说http://baike.baidu.com/view/717633.htm 以一个传说中的问题为例子,提供源代码主要是能够通过这个问题,了解如何来操作循环链表 在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止.然而Josephus 和他的朋友并不想遵从.

一个小笔记(1):设置重启电脑、自动启动

[设置重启电脑] 使用API函数ExitWindowsEx  BOOL WINAPI ExitWindowsEx(  _In_ UINT  uFlags,  _In_ DWORD dwReason); [MSDN]https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=ZH-CN&k=k(winuser%2FExitWindowsEx);k(ExitWindowsEx);k(DevLang-C%2B%2B);k(Tar

一个小笔记(2):Socket网络编程

网络通信的流程: 服务器端申请套接字 -> 绑定套接字到本地,打开端口 -> 监听端口 -> 等待接受消息 -> 有消息之后,读取消息 客户端申请套接字 -> 向服务端发起连接 -> 连接成功后,可以随时发送消息 啥是套接字?http://baike.baidu.com/link?url=BfywKEhH0b4vASGaFSZw9Dwwh2hQgV2DdE4POM2_5Xl80RK1_2hbH3YFQaFzfrxKeqh8SbcMcgRTP-Wj88Zb5a 简单的一个

每天一个小算法(3)----倒序打印链表

这个比较简单,用栈.递归.倒转链表都可以实现,不再过多解释. 代码使用递归实现 1 #include <stdio.h> 2 #include <time.h> 3 #include <stdlib.h> 4 typedef struct Node 5 { 6 int data; 7 Node* next; 8 }Node, *List; 9 10 11 List createList(int num) //随机生成数字,构造链表 12 { 13 List aList

每天一个小算法(2)----合并两个有序链表

每天一个小算法还是有点没时间,尽量抽出时间写一写. 今天是合并有序的链表,对单链表有点忘了,尤其是指针指来指去的,有点晕,幸好基础还算好,想了想还是能想回来. 代码使用随机数函数生成一个链表,然后对链表排序,最后合并链表并打印,删除链表的函数于算法无关紧要,所以未实现^_^. 在Linux/g++下编译运行成功. 合并思路:和合并数组有些类同,比较两个节点的元素大小然后将小的摘下来尾插到链表bList中,然后指针指向下一个节点,最后直接把非空的链表合并到bList的末尾. 1 #include