智能尺子-普宁老趣边网络有限公司
更多分类

A*搜索算法求解罗马尼亚问题

2024-12-29

  A*算法罕用于 二维舆图途径布局&#Vff0c;算法所给取的启示式搜寻可以操做真际问题所具备的启示式信息来辅导搜寻&#Vff0c;从而减少搜寻领域&#Vff0c;控制搜寻范围&#Vff0c;降低真际问题的复纯度。

2.算法本理&#Vff1a;

  A*算法的本理是设想一个价钱预计函数&#Vff1a;此中

f(n)=g(n)+h(n)

评价函数F(n)

界说&#Vff1a;从起始节点通过节点n的达到目的节点的最小价钱途径的预计值&#Vff1b;

做用&#Vff1a;依据 F(n)可以计较出当前节点的价钱&#Vff0c;并可以对下一次能够达到的节点停行评价。

函数G(n)

界说&#Vff1a;从起始节点到n节点的已走过途径的真际价钱&#Vff1b;

函数H(n)

界说&#Vff1a;从n节点到目的节点可能的最劣途径的预计价钱 。

做用&#Vff1a; H(n)讲明了算法运用的启示信息&#Vff0c;它起源于人们对途径布局问题的认识&#Vff0c;依赖某种经历预计。

给取每次搜寻都找到价钱值最小的点再继续往外搜寻的历程&#Vff0c;一步一步找到最劣途径。

3.评估

齐备性&#Vff1a;需价钱小于就是C*(最劣解途径的价钱值)的结点是有穷的&#Vff0c;每步价钱都赶过ε并且b是有穷的。

最劣性&#Vff1a;需满足可采用性&#Vff08;--树搜寻最劣&#Vff09;和一致性&#Vff08;图搜寻最劣&#Vff09;

4.可采用性取一致性

可承受&#Vff1a; 应付任何形态n&#Vff0c;满足h(n) h*(n)&#Vff0c; 此中h*(n)默示从n到目的形态的真际最小价钱。

留心&#Vff1a;下面的应该是小于就是&#Vff0c;而非小于&#Vff1b;

一致&#Vff1a; 应付任何形态n和其后继形态n'&#Vff0c;满足h(n) ≤ c(n, n') + h(n')&#Vff0c;此中c(n, n')默示从n到n'的真际价钱。

5.图搜寻取树搜寻

图搜寻&#Vff1a;不允许重复会见结点&#Vff0c;即OPEN表 ∩ CLOSED表 = ø&#Vff1b;

树搜寻&#Vff1a;允许重复会见结点。

举例&#Vff1a;&#Vff08;那也是2018年第二学期的期中检验题&#Vff09;

&#Vff08;1&#Vff09;题目问题

&#Vff08;2&#Vff09;树搜寻

&#Vff08;3&#Vff09;图搜寻

觉得上面的图也有些瑕疵&#Vff0c;下面是笔者画的&#Vff1a;

三、实验内容及轨范 0.真训内容&#Vff1a;2-1第三章 通过搜寻停行问题求解

题目问题&#Vff1a;罗马尼亚问题

  agent正在罗马尼亚度假&#Vff0c;目前位于 Arad 都市。agent明天有航班从Bucharest 起飞&#Vff0c;不能改签退票。

        如今你须要寻找到 Bucharest 的最短途径&#Vff0c;正在左侧编辑器补充ZZZoid A_star(int goal,node &src,Graph &graph)函数&#Vff0c;运用编写的搜寻算法代码求解罗马尼亚问题&#Vff1a;

预期输出&#Vff1a;

solution: 0-> 15-> 14-> 13-> 1-> end cost:418 1.创立搜寻树&#Vff1b; (1)给每个都市编号 #define A 0 #define B 1 #define C 2 #define D 3 #define E 4 #define F 5 #define G 6 #define H 7 #define I 8 #define L 9 #define M 10 #define N 11 #define O 12 #define P 13 #define R 14 #define S 15 #define T 16 #define U 17 #define x 18 #define Z 19 (2)启示函数--h数组赋值

结点n距离起点的或许价钱&#Vff0c;给取曲线距离&#Vff1b;

int h[20] =//从n节点到目的节点可能的最劣途径的预计价钱 { 366,0,160,242,161, 178,77,151,226,244, 241,234,380,98,193, 253,329,80,199,374 }; (3)struct都市节点

每个结点保存其g(n)&#Vff0c;h(n)&#Vff0c;f(n)=g(n)+h(n)。

重载<&#Vff1a;每主要与出f(n)最小的结点&#Vff0c;便于对结点停行牌序。

struct node {    int g;                              //从起始节点到n节点的已走过途径的真际价钱    int h;                              //从n节点到目的节点可能的最劣途径的预计价钱    int f;                              //价钱预计函数    int name;    node(int name, int g, int h) {       //结构函数        this->name = name;        this->g = g;        this->h = h;        this->f = g + h;   }; ​    //重载运算符    bool operator <(const node& a)const { return f < a.f; } }; (4)class图 class Graph        //图构造 { public:    Graph() {        memset(graph, -1, sizeof(graph));   //图初始化为-1&#Vff0c;代表无边   } ​    int getEdge(int from, int to) {       //获与边的开销        return graph[from][to];   } ​    ZZZoid addEdge(int from, int to, int cost) {    //新删一条边及其开销        if (from >= 20 || from < 0 || to >= 20 || to < 0)            return;        graph[from][to] = cost;   } ​    ZZZoid init() {                        //图初始化        addEdge(O, Z, 71);        addEdge(Z, O, 71); ​        addEdge(O, S, 151);        addEdge(S, O, 151); ​        addEdge(Z, A, 75);        addEdge(A, Z, 75); ​        addEdge(A, S, 140);        addEdge(S, A, 140); ​        addEdge(A, T, 118);        addEdge(T, A, 118); ​        addEdge(T, L, 111);        addEdge(L, T, 111); ​        addEdge(L, M, 70);        addEdge(M, L, 70); ​        addEdge(M, D, 75);        addEdge(D, M, 75); ​        addEdge(D, C, 120);        addEdge(C, D, 120); ​        addEdge(C, R, 146);        addEdge(R, C, 146); ​        addEdge(S, R, 80);        addEdge(R, S, 80); ​        addEdge(S, F, 99);        addEdge(F, S, 99); ​        addEdge(F, B, 211);        addEdge(B, F, 211); ​        addEdge(P, C, 138);        addEdge(C, P, 138); ​        addEdge(R, P, 97);        addEdge(P, R, 97); ​        addEdge(P, B, 101);        addEdge(B, P, 101); ​        addEdge(B, G, 90);        addEdge(G, B, 90); ​        addEdge(B, U, 85);        addEdge(U, B, 85); ​        addEdge(U, H, 98);        addEdge(H, U, 98); ​        addEdge(H, E, 86);        addEdge(E, H, 86); ​        addEdge(U, x, 142);        addEdge(x, U, 142); ​        addEdge(I, x, 92);        addEdge(x, I, 92); ​        addEdge(I, N, 87);        addEdge(N, I, 87);   } ​ priZZZate:    int graph[20][20];              //图数组&#Vff0c;用来保存图信息&#Vff0c;最多有20个节点 }; (5)其余队列、记录途径数组 bool list[20]; //记录节点能否正在当前队列中 ZZZector<node> openList; //扩展队列 bool closeList[20]; //记录节点能否被扩展&#Vff08;选择&#Vff09;过 stack<int> road; //记录途径 int parent[20]; //记录途径 (6)打印函数

打印途径和开销&#Vff1a;ZZZoid print_result(Graph &graph)

ZZZoid print_result(Graph &graph) {    int p = openList[0].name;    int lastNodeNum;    road.push(p);    while (parent[p] != -1)   {        road.push(parent[p]);        p = parent[p];   }    lastNodeNum = road.top();    int cost = 0;    cout << "solution: ";    while (!road.empty())   {        cout << road.top() << "-> ";        if (road.top() != lastNodeNum)       {            cost += graph.getEdge(lastNodeNum, road.top());            lastNodeNum = road.top();       }        road.pop();   }    cout << "end" << endl;    cout << "cost:" << cost; } 2.真现A*搜寻算法&#Vff1b;

实验平台任务&#Vff1a;补充ZZZoid A_star(int goal,node &src,Graph &graph)函数&#Vff1b;

末点入队&#Vff1b;

只有扩展队列非空&#Vff0c;就不停从扩展队列中与队首节点停行扩展&#Vff1a;

扩展结点为目的结点&#Vff1a;搜寻完毕。

扩展结点非目的结点&#Vff1a;考查取扩展节点有边相连&#Vff0c;且未扩展过的节点&#Vff1a;

新结点正在扩展队列中&#Vff1a;检验测验以当前扩展节点为中继&#Vff0c;更新g(n)和f(n)&#Vff1b;

新结点不正在扩展队列中&#Vff1a;间接结构新结点并参预队列&#Vff1b;

扩展完毕后&#Vff0c;对队列停行牌序&#Vff0c;担保继续与出f(n)最小的结点扩展。

ZZZoid A_star(int goal,node &src,Graph &graph) {    openList.push_back(src); //末点入队    sort(openList.begin(), openList.end());        while (!openList.empty())//队列中另有可扩展节点&#Vff0c;就不停扩展   {        /********** Begin **********/        node n=openList[0];        if(n.name==goal) return; //扩展节点是目的节点&#Vff0c;搜寻完毕        openList.erase(openList.begin());        closeList[n.name]=1; //当前节点已扩展        list[n.name]=0; //当前节点出队        for(int i=0;i<20;i++){            if(graph.getEdge(n.name,i)!=-1 && closeList[i]!=1){                int cost=n.g+graph.getEdge(n.name,i);//到下一个都市的价钱                if(list[i]){                    //更新已有节点                    for(int j=0;j<openList.size();j++){                        if(openList[j].name==i){                            if(openList[j].g>cost){                                openList[j].g=cost;                                openList[j].f=cost+openList[j].h;                                parent[i]=n.name;                           }                            break;                       }                   }               }                else{                    //结构新节点                    node newNode(i,cost,h[i]);                    openList.push_back(newNode);                    list[i]=1;                    parent[i]=n.name;               }           }       }        sort(openList.begin(),openList.end()); /********** End **********/     } } 测试版原&#Vff1a; ZZZoid A_star(int goal, node& src, Graph& graph)//A*搜寻算法 {    openList.push_back(src);                    //扩展汇折参预起始节点    sort(openList.begin(), openList.end());     //牌序扩展汇折的节点&#Vff0c;以与出价钱最小的节点    for(auto V:openList) cout<<V.name<<" "; cout<<endl; ​    while (!openList.empty())   {        /********** Begin **********/        node curNode = openList[0];             //与出扩展汇折第一个节点&#Vff0c;即价钱最小的节点                cout<<"当前扩展节点&#Vff1a;"<<ch[curNode.name]<<endl;        if (curNode.name == goal) {             //假如当前节点便是目的节点&#Vff0c;则退出       cout<<"\t当前扩展节点为GOAL"<<endl;            return;       }        openList.erase(openList.begin());       //将当前节点从扩展列表中增除        closeList[curNode.name] = true;         //将当前节点参预已会见节点        list[curNode.name] = false;             //符号当前节点已不正在扩展汇折中 ​        for (int i = 0; i < 20; i++) {                      //初步扩展当前节点&#Vff0c;即找到其邻居节点            if (graph.getEdge(i, curNode.name) == -1) {     //若不是当前节点的邻居节点&#Vff0c;跳到下一个节点                continue;           }            if (closeList[i]) {                             //若此节点已参预已会见汇折closeList&#Vff0c;也跳到下一个节点           cout<<"\t节点--"<<ch[i]<<" 已会见过"<<endl;                continue;           }            cout<<"\t节点--"<<ch[i]<<" 未会见过&#Vff0c;且取当前扩展节点--"<<ch[curNode.name]<<"有边相连"<<endl;            int g1 = curNode.g + graph.getEdge(i, curNode.name);    //计较起始节点到当前节点i的g值            int h1 = h[i];                                          //与恰当前节点i的h值            if (list[i]) {                                          //假如节点i正在openList中           cout<<"\t\t节点--"<<ch[i]<<" 正在扩展节点汇折中"<<endl;                for (int j = 0; j < openList.size(); j++) {                    if (i == openList[j].name) {                    //首先找到节点i的位置&#Vff0c;即j                        if (g1 < openList[j].g) {                   //假如新的途径的花销更小&#Vff0c;则更新                       cout<<"\t\t\t新途径花销更小&#Vff0c;更新"<<endl;                            openList[j].g = g1;                            openList[j].f = g1 + openList[j].h;                            parent[i] = curNode.name;               //记录父节点                            break;                       }                        cout<<"\t\t\t新途径花销不会更劣&#Vff0c;不更新"<<endl;                   }               }           }            else {                        //假如节点i不正在openList&#Vff0c;则将其参预此中&#Vff08;因为扩展时会见了它&#Vff09;           cout<<"\t\t节点--"<<ch[i]<<" 不正在扩展节点汇折中"<<endl;           cout<<"\t\t\t创立新节点&#Vff0c;参预扩展队列"<<endl;                node newNode(i, g1, h1);                    //创立新节点&#Vff0c;其参数已知                openList.push_back(newNode);                //新节点参预openList中                parent[i] = curNode.name;                   //记录父节点                list[i] = true;                             //记录节点i参预了openList           }       }        cout<<"openList: "; for(auto V:openList) cout<<ch[V.name]<<"-"<<V.f<<" "; cout<<endl;        sort(openList.begin(), openList.end());     //扩展完当前节点后要对openList从头牌序        cout<<"openList-sorted: "; for(auto V:openList) cout<<ch[V.name]<<"-"<<V.f<<" "; cout<<endl<<endl;        /********** End **********/   } }

 输出结果&#Vff1a;

 解空间树&#Vff1a;

3.运用编写的搜寻算法代码求解罗马尼亚问题

4.阐明算法的光阳复纯度

启示式函数的误差&#Vff1a;

绝对误差&#Vff1a;

\Delta = h^{*}-h

相对误差&#Vff1a;

\varepsilon = \frac{h^{*}-h}{h^{*}}

光阳复纯度

最大绝对误差下的复纯度&#Vff1a;

O(b^{\Delta})

思考每轨范价钱为常质&#Vff1a;

O(b^{\varepsilon d})

四、考虑题 1.几多种搜寻算法最劣性的比较

宽度劣先搜寻&#Vff0c;深度劣先搜寻&#Vff0c;一致价钱搜寻&#Vff0c;迭代加深的深度劣先搜寻算法哪种办法最劣&#Vff1f;

ε每步碾儿动价钱都相等时&#Vff0c;宽度劣先搜寻迭代加深的深度劣先搜寻最劣&#Vff0c;否则一致搜寻价钱算法最劣

宽度劣先算法&#Vff1a;

齐备性&#Vff1a;正在最浅的目的处于有限深度时是齐备的&#Vff1b;

最劣性&#Vff1a;途径价钱基于结点深度的非递加函数时才是最劣的&#Vff0c;最典型的便是动做价钱相等的状况&#Vff1b;

迭代加深的深度劣先搜寻类似&#Vff0c;且二者光阳复纯度取空间复纯度也雷同。

一致价钱搜寻&#Vff1a;最劣的&#Vff1b;

扩展途径泯灭最小的结点&#Vff0c;由于价钱非负&#Vff0c;第一个被扩展的目的结点一定是最劣解。

但可能会摸索价钱小的动做的搜寻树&#Vff0c;开销更大。

深度劣先搜寻&#Vff1a;既不是齐备的&#Vff0c;也不是最劣的。

2.贪婪最佳劣先搜寻和A*搜寻这种办法最劣&#Vff1f;

A*搜寻算法是最劣的。

贪婪最佳劣先搜寻&#Vff1a;不具有齐备性&#Vff0c;也不具有最劣性&#Vff0c;能否找到最劣解取启示式函数有关。

A*搜寻算法&#Vff1a;

最劣性&#Vff1a;满足可采用性和一致性便是最劣的&#Vff1b;

齐备性&#Vff1a;只有分收是有限的便是齐备的。

3.阐明比较无信息搜寻战略和有信息搜寻战略

无信息搜寻战略&#Vff1a;

弊病&#Vff1a;自发的搜寻&#Vff0c;可能须要较大的光阳开销和空间开销威力找到解&#Vff1b;

劣点&#Vff1a;具有好的通用性。

有信息搜寻战略&#Vff1a;

弊病&#Vff1a;机能取启示式函数的量质有关

劣点&#Vff1a;通过启示式函数操做问题的格外信息&#Vff0c;正在搜寻历程中向着可能有最劣解的标的目的推进&#Vff0c;能够进步搜寻效率。

五、代码汇总 1.提交版原 #include<iostream> #include<ZZZector> #include<memory.h> #include<stack> #include<algorithm> #define A 0 #define B 1 #define C 2 #define D 3 #define E 4 #define F 5 #define G 6 #define H 7 #define I 8 #define L 9 #define M 10 #define N 11 #define O 12 #define P 13 #define R 14 #define S 15 #define T 16 #define U 17 #define x 18 #define Z 19 ​ using namespace std; ​ int h[20] = { 366,0,160,242,161, 178,77,151,226,244, 241,234,380,98,193, 253,329,80,199,374 }; ​ struct node {    int g;    int h;    int f;    int name;    node(int name, int g, int h)   {        this->name = name;        this->g = g;        this->h = h;        this->f = g + h;   };    bool operator <(const node &a)const   {        return f < a.f;   } }; ​ ​ class Graph { public:    Graph()   {        memset(graph, -1, sizeof(graph));   }    int getEdge(int from, int to)   {        return graph[from][to];   }    ZZZoid addEdge(int from, int to, int cost)   {        if (from >= 20 || from < 0 || to >= 20 || to < 0)            return;        graph[from][to] = cost;   }     ZZZoid init(){        addEdge(O, Z, 71);        addEdge(Z, O, 71); ​        addEdge(O, S, 151);        addEdge(S, O, 151); ​        addEdge(Z, A, 75);        addEdge(A, Z, 75); ​        addEdge(A, S, 140);        addEdge(S, A, 140); ​        addEdge(A, T, 118);        addEdge(T, A, 118); ​        addEdge(T, L, 111);        addEdge(L, T, 111); ​        addEdge(L, M, 70);        addEdge(M, L, 70); ​        addEdge(M, D, 75);        addEdge(D, M, 75); ​        addEdge(D, C, 120);        addEdge(C, D, 120); ​        addEdge(C, R, 146);        addEdge(R, C, 146); ​        addEdge(S, R, 80);        addEdge(R, S, 80); ​        addEdge(S, F, 99);        addEdge(F, S, 99); ​        addEdge(F, B, 211);        addEdge(B, F, 211); ​        addEdge(P, C, 138);        addEdge(C, P, 138); ​        addEdge(R, P, 97);        addEdge(P, R, 97); ​        addEdge(P, B, 101);        addEdge(B, P, 101); ​        addEdge(B, G, 90);        addEdge(G, B, 90); ​        addEdge(B, U, 85);        addEdge(U, B, 85); ​        addEdge(U, H, 98);        addEdge(H, U, 98); ​        addEdge(H, E, 86);        addEdge(E, H, 86); ​        addEdge(U, x, 142);        addEdge(x, U, 142); ​        addEdge(I, x, 92);        addEdge(x, I, 92); ​        addEdge(I, N, 87);        addEdge(N, I, 87); } ​ priZZZate:    int graph[20][20]; }; ​ bool list[20]; //记录节点能否正在当前队列中 ZZZector<node> openList;//扩展队列 bool closeList[20];//记录节点能否被扩展&#Vff08;选择&#Vff09;过 stack<int> road;//记录途径 int parent[20];//记录途径 ​ ZZZoid A_star(int goal,node &src,Graph &graph) {    openList.push_back(src); //末点入队    sort(openList.begin(), openList.end());        while (!openList.empty())//队列中另有可扩展节点&#Vff0c;就不停扩展   {        /********** Begin **********/        node n=openList[0];        if(n.name==goal) return; //扩展节点是目的节点&#Vff0c;搜寻完毕        openList.erase(openList.begin());        closeList[n.name]=1; //当前节点已扩展        list[n.name]=0; //当前节点出队        for(int i=0;i<20;i++){            if(graph.getEdge(n.name,i)!=-1 && closeList[i]!=1){                int cost=n.g+graph.getEdge(n.name,i);//到下一个都市的价钱                if(list[i]){                    //更新已有节点                    for(int j=0;j<openList.size();j++){                        if(openList[j].name==i){                            if(openList[j].g>cost){                                openList[j].g=cost;                                openList[j].f=cost+openList[j].h;                                parent[i]=n.name;                           }                            break;                       }                   }               }                else{                    //结构新节点                    node newNode(i,cost,h[i]);                    openList.push_back(newNode);                    list[i]=1;                    parent[i]=n.name;               }           }       }        sort(openList.begin(),openList.end()); /********** End **********/     } } ​ ZZZoid print_result(Graph &graph) {    int p = openList[0].name;    int lastNodeNum;    road.push(p);    while (parent[p] != -1)   {        road.push(parent[p]);        p = parent[p];   }    lastNodeNum = road.top();    int cost = 0;    cout << "solution: ";    while (!road.empty())   {        cout << road.top() << "-> ";        if (road.top() != lastNodeNum)       {            cost += graph.getEdge(lastNodeNum, road.top());            lastNodeNum = road.top();       }        road.pop();   }    cout << "end" << endl;    cout << "cost:" << cost; } 2.测试版原 #include<iostream> #include<ZZZector> #include<memory.h> #include<stack> #include<algorithm> ​ #define A 0 #define B 1 #define C 2 #define D 3 #define E 4 #define F 5 #define G 6 #define H 7 #define I 8 #define L 9 #define M 10 #define N 11 #define O 12 #define P 13 #define R 14 #define S 15 #define T 16 #define U 17 #define x 18 #define Z 19 ​ using namespace std; string ch="ABCDEFGHILMNOPRSTUxZ"; ​ ​ ​ int h[20] =//从n节点到目的节点可能的最劣途径的预计价钱 { 366,0,160,242,161, 178,77,151,226,244, 241,234,380,98,193, 253,329,80,199,374 }; ​ ​ /* *一个节点构造&#Vff0c;node */ struct node {    int g;                              //从起始节点到n节点的已走过途径的真际价钱    int h;                              //从n节点到目的节点可能的最劣途径的预计价钱    int f;                              //价钱预计函数    int name;    node(int name, int g, int h) {       //结构函数        this->name = name;        this->g = g;        this->h = h;        this->f = g + h;   }; ​    //重载运算符    bool operator <(const node& a)const { return f < a.f; } }; ​ ​ class Graph        //图构造 { public:    Graph() {        memset(graph, -1, sizeof(graph));   //图初始化为-1&#Vff0c;代表无边   } ​    int getEdge(int from, int to) {       //获与边的开销        return graph[from][to];   } ​    ZZZoid addEdge(int from, int to, int cost) {    //新删一条边及其开销        if (from >= 20 || from < 0 || to >= 20 || to < 0)            return;        graph[from][to] = cost;   } ​    ZZZoid init() {                        //图初始化        addEdge(O, Z, 71);        addEdge(Z, O, 71); ​        addEdge(O, S, 151);        addEdge(S, O, 151); ​        addEdge(Z, A, 75);        addEdge(A, Z, 75); ​        addEdge(A, S, 140);        addEdge(S, A, 140); ​        addEdge(A, T, 118);        addEdge(T, A, 118); ​        addEdge(T, L, 111);        addEdge(L, T, 111); ​        addEdge(L, M, 70);        addEdge(M, L, 70); ​        addEdge(M, D, 75);        addEdge(D, M, 75); ​        addEdge(D, C, 120);        addEdge(C, D, 120); ​        addEdge(C, R, 146);        addEdge(R, C, 146); ​        addEdge(S, R, 80);        addEdge(R, S, 80); ​        addEdge(S, F, 99);        addEdge(F, S, 99); ​        addEdge(F, B, 211);        addEdge(B, F, 211); ​        addEdge(P, C, 138);        addEdge(C, P, 138); ​        addEdge(R, P, 97);        addEdge(P, R, 97); ​        addEdge(P, B, 101);        addEdge(B, P, 101); ​        addEdge(B, G, 90);        addEdge(G, B, 90); ​        addEdge(B, U, 85);        addEdge(U, B, 85); ​        addEdge(U, H, 98);        addEdge(H, U, 98); ​        addEdge(H, E, 86);        addEdge(E, H, 86); ​        addEdge(U, x, 142);        addEdge(x, U, 142); ​        addEdge(I, x, 92);        addEdge(x, I, 92); ​        addEdge(I, N, 87);        addEdge(N, I, 87);   } ​ priZZZate:    int graph[20][20];              //图数组&#Vff0c;用来保存图信息&#Vff0c;最多有20个节点 }; ​ bool list[20];                          //用于记录节点i能否正在openList汇折中 ZZZector<node> openList;                  //扩展节点汇折 bool closeList[20];                     //已会见节点汇折 stack<int> road;                        //途径 int parent[20];                         //父节点&#Vff0c;用于回溯结构途径 ​ ZZZoid A_star(int goal, node& src, Graph& graph)//A*搜寻算法 {    openList.push_back(src);                    //扩展汇折参预起始节点    sort(openList.begin(), openList.end());     //牌序扩展汇折的节点&#Vff0c;以与出价钱最小的节点    for(auto V:openList) cout<<V.name<<" "; cout<<endl; ​    while (!openList.empty())   {        /********** Begin **********/        node curNode = openList[0];             //与出扩展汇折第一个节点&#Vff0c;即价钱最小的节点                cout<<"当前扩展节点&#Vff1a;"<<ch[curNode.name]<<endl;        if (curNode.name == goal) {             //假如当前节点便是目的节点&#Vff0c;则退出       cout<<"\t当前扩展节点为GOAL"<<endl;            return;       }        openList.erase(openList.begin());       //将当前节点从扩展列表中增除        closeList[curNode.name] = true;         //将当前节点参预已会见节点        list[curNode.name] = false;             //符号当前节点已不正在扩展汇折中 ​        for (int i = 0; i < 20; i++) {                      //初步扩展当前节点&#Vff0c;即找到其邻居节点            if (graph.getEdge(i, curNode.name) == -1) {     //若不是当前节点的邻居节点&#Vff0c;跳到下一个节点                continue;           }            if (closeList[i]) {                             //若此节点已参预已会见汇折closeList&#Vff0c;也跳到下一个节点           cout<<"\t节点--"<<ch[i]<<" 已会见过"<<endl;                continue;           }            cout<<"\t节点--"<<ch[i]<<" 未会见过&#Vff0c;且取当前扩展节点--"<<ch[curNode.name]<<"有边相连"<<endl;            int g1 = curNode.g + graph.getEdge(i, curNode.name);    //计较起始节点到当前节点i的g值            int h1 = h[i];                                          //与恰当前节点i的h值            if (list[i]) {                                          //假如节点i正在openList中           cout<<"\t\t节点--"<<ch[i]<<" 正在扩展节点汇折中"<<endl;                for (int j = 0; j < openList.size(); j++) {                    if (i == openList[j].name) {                    //首先找到节点i的位置&#Vff0c;即j                        if (g1 < openList[j].g) {                   //假如新的途径的花销更小&#Vff0c;则更新                       cout<<"\t\t\t新途径花销更小&#Vff0c;更新"<<endl;                            openList[j].g = g1;                            openList[j].f = g1 + openList[j].h;                            parent[i] = curNode.name;               //记录父节点                            break;                       }                        cout<<"\t\t\t新途径花销不会更劣&#Vff0c;不更新"<<endl;                   }               }           }            else {                        //假如节点i不正在openList&#Vff0c;则将其参预此中&#Vff08;因为扩展时会见了它&#Vff09;           cout<<"\t\t节点--"<<ch[i]<<" 不正在扩展节点汇折中"<<endl;           cout<<"\t\t\t创立新节点&#Vff0c;参预扩展队列"<<endl;                node newNode(i, g1, h1);                    //创立新节点&#Vff0c;其参数已知                openList.push_back(newNode);                //新节点参预openList中                parent[i] = curNode.name;                   //记录父节点                list[i] = true;                             //记录节点i参预了openList           }       }        cout<<"openList: "; for(auto V:openList) cout<<ch[V.name]<<"-"<<V.f<<" "; cout<<endl;        sort(openList.begin(), openList.end());     //扩展完当前节点后要对openList从头牌序        cout<<"openList-sorted: "; for(auto V:openList) cout<<ch[V.name]<<"-"<<V.f<<" "; cout<<endl<<endl;        /********** End **********/   } } ​ ZZZoid print_result(Graph& graph)     //用于打印途径和开销 { cout<<"\nparent数组&#Vff1a;"<<endl; for(int i=0;i<20;i++) if(parent[i]!=-1) cout<<"节点--"<<ch[i]<<"的父节点是&#Vff1a;"<<ch[parent[i]]<<endl; cout<<endl;    int p = openList[0].name;       //p即为目的节点    int lastNodeNum;    road.push(p);                   //目的节点压入栈中&#Vff0c;之后最后才输出    while (parent[p] != -1)         //不停回溯与得一条完好途径   {        road.push(parent[p]);        p = parent[p];   }    lastNodeNum = road.top();       //起始节点    int cost = 0;                   //总开销    cout << "solution: ";    while (!road.empty())           //栈不为空就继续循环   {        cout << road.top() << "-> ";        if (road.top() != lastNodeNum)  //假如栈顶元素不是起点       {            cost += graph.getEdge(lastNodeNum, road.top());     //添加花销            lastNodeNum = road.top();       //更新栈顶元素       }        road.pop();     //弹出栈顶元素   }    cout << "end" << endl;    cout << "cost:" << cost; } ​ int main() {    Graph graph;    graph.init();    int goal = B;                           //目的节点B    node src(A, 0, h[A]);                   //起始节点A    list[A] = true;    memset(parent, -1, sizeof(parent));     //初始化parent    memset(list, false, sizeof(list));      //初始化list    A_star(goal, src, graph);    print_result(graph);    return 0; } 另&#Vff1a;第一章-绪论