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;

    }

}

 

 

 

 

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

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

    网络通信的流程: 服务器端申请套接字 -> 绑定套接字到本地,打开端口 -> 监听端口 -> 等待接受消息 -> 有消息之后,读取消息 客户端申请套接字 -> 向服务端发 ...

  2. 学习完nio的一个小笔记吧

    这是一个nio网络通信服务端的demo,主要就学习了selector的一些用法,以及它里面的事件类型 selector是对nio的一个优化,它能保证既能高效处理线程中的事件,又能保证线程不会一直占用c ...

  3. 一个小笔记(8):EN_2

    Why is programming fun? What delights may its practitioner expect as his reward? First is the sheer ...

  4. 一个小笔记(7):EN_1

    For nearly ten years, the Unified Modeling Language(UML) has been the industry standard for visualiz ...

  5. JavaScript关于返回数据类型一个小小的笔记

    Javascript关于返回数据类型的一个小笔记 javascript数据类型有两种. 一种是基本数据类型:String.Number.Boolean.Symbol.Underfine.Null 一种 ...

  6. c++学习笔记---04---从另一个小程序接着说

    从另一个小程序接着说 文件I/O 前边我们已经给大家简单介绍和演示过C和C++在终端I/O处理上的异同点. 现在我们接着来研究文件I/O. 编程任务:编写一个文件复制程序,功能实现将一个文件复制到另一 ...

  7. c++学习笔记---03---从一个小程序说起2

    从一个小程序说起2 要求:编写一个程序,要求用户输入一串整数和任意数目的空格,这些整数必须位于同一行中,但允许出现在该行中的任何位置.当用户按下键盘上的"Enter"键时,数据输入 ...

  8. c++学习笔记---02---从一个小程序说起

    从一个小程序说起 这一讲的主要目的是帮助大家在C语言的背景知识上与C++建立联系. 问题探索 问题:对一个整型数组求和. 要求:定义一个存储着 n 个元素的数组,要求用C语言完成这个任务. 赶紧的:大 ...

  9. python笔记_查看函数调用栈的一个小技巧

    一.背景 最近在看一个开源框架的源码,涉及到的内容非常杂乱,有的函数不知道是在什么时候被谁给调用了?调用的时候传入了什么参数?为了解决这个问题,写了一个小的装饰器. 二.实现 这个装饰器函数主要参考了 ...

随机推荐

  1. 创建Python本地副本

    创建本地副本后可以避免解释器找不到模块的情况. 1. 创建一个测试用的pl.py def printTest(): print("this is a test") 2. 将pl.p ...

  2. 康少带你python项目从部署到上线云服务器

    首先,服务器要安装nginx和mysql,网站文件建议放在/usr/local/www,环境python3.6+mysql5.7,阿里云的服务器可以用公共镜像有一个配置好的,不然就自己装一下环境吧. ...

  3. perl 打开二进制文件,并拷贝内容

    实现脚本 use strict ; my $fileName = "/Users/chenfool/Desktop/sequoiadb-大数据平台构建.pdf" ; my $out ...

  4. LVS 负载均衡器总结

    下面部分原理部分,是从网上摘录,源网址已经无从获取,我将其中一小部分模糊的说明加入了一些自己的理解,仅最大可能让全文容易阅读,也方便自己以后参考,若你是大牛希望能给我一些宝贵的建议,将理解有误的地方加 ...

  5. bzoj2825:[AHOI2012]收集资源

    传送门 看到数据范围这么小,就没想过暴力的办法么 考虑肯定是从近走到远,所以走的点之间一定没有其他的点,所以我们就可以暴力的建图,然后暴力的去dfs就好了 代码: #include<cstdio ...

  6. dream(2018.10.17)

    一句话题意:讲什么题意啊,见usaco2017feb silver的T1,一模一样,就是牛和鸡的读入顺序反过来了一下,数据范围大了10倍,卡掉了\(O(n^2)\)的算法. 数据范围: 对于 30%的 ...

  7. Git - .gitignore怎么忽略已经被版本控制的文件

    问题 如果某个文件已经存在于远程仓库了,也就是说某个文件已经被版本控制了,如果将该文件添加到.gitignore中,是无法生效的.因为.gitignore是用来控制尚未被纳入版本控制的文件,如果文件已 ...

  8. PAT甲级——1134 Vertex Cover (25 分)

    1134 Vertex Cover (考察散列查找,比较水~) 我先在CSDN上发布的该文章,排版稍好https://blog.csdn.net/weixin_44385565/article/det ...

  9. 缺少mscvr100.dll

    最后使用百度电脑专家修复好的!

  10. Codeforces 1142E(图、交互)

    题目传送 官方题解说的很好了,剩下的就是读大佬代码了,前面是tarjan求SCC缩点图.我图论没学过,接下来删点是怎么操作看得有点头秃,直到我看到了%%%安德鲁何神仙的代码. 按照题面连通紫线以后,我 ...