[小明学算法]3.启发式搜索算法----A*算法之我见

1.算法介绍

a*算法是一种寻路算法,类似于图的广度优先遍历搜索.

2.基本概念

设计先两个集合CloseList和OpenList,CloseList表示已经走过的节点,OpenList中的节点表示所有我们可以选择的下一步节点.

3.计算步骤:

1.将起点设为当前节点,并创建OpenList和CloseList.

2.将当前节点从OpenList中删除,并加入到CloseList中.

3.遍历当前节点的可到达节点,不包括CloseList中的节点,记录为AroundList,

4.然后对每个AroundList中的节点进行估值,f(x)=g(x)+h(x)

  ①.计算g(x).g(x)是消耗记录值,表示走过的路程所需要消耗的值,为当前节点的g值加上与当前节点的距离值.同时需将估值节点的加入OpenList并将估值节点的父节点设为当前节点.

    在计算g(x),需要注意此节点已存在于OpenList中,而且新g(x)小于原g(x),则更改g(x)的值,并更改当此节点的父节点为当前节点,否则不做修改.

  ②h(x)其中,g(x)表示估值算法,计算其与目标位置距离的估值.

    h(x)就是启发式搜索的估值函数,此函数写的越好,算法的效率就越高

5.若未到达目标节点,执行6,若到达目标节点,执行7

6.选择OpenList当中f(x)最小的点,设为当前节点,重复以上步骤2,3,4,5..

7.通过当前节点的父节点属性一直往上遍历,则得到目标路径节点的倒序排列.

 

4.代码实现

  1 using System.Collections.Generic;
  2 
  3 namespace 动态规划
  4 {
  5     internal class Program
  6     {
  7         readonly List<Node> OpenList = new List<Node>();
  8         readonly List<Node> CloseList = new List<Node>();
  9 
 10         List<Node> FindWayByAStart(Node startNode, Node endNode)
 11         {
 12             //1.将当前节点加入到CloseList中,并从OpenList中删除
 13             CloseList.Add(startNode);
 14             if (OpenList.Contains(startNode))
 15                 OpenList.Remove(startNode);
 16             //2.寻找当前节点所有可以到达的节点
 17             //且可到达的节点并不再CloseList中,则加入AroundList
 18             //TODO
 19             var aroundList = new List<Node>();
 20 
 21             //3.对AroundList中的每个节点计算f(x)=g(x)+h(x)的值
 22             foreach (Node curNode in aroundList)
 23             {      
 24                 if (!OpenList.Contains(curNode))
 25                 { 
 26                     //如果此节点不在OpenList中,正常估值
 27                     //将此节点加入到OpenList中,并将其父节点设为当前节点
 28                     curNode.G = GetGValue(curNode, startNode) + startNode.G;
 29                     curNode.H = GetHValue(curNode, endNode);
 30                     curNode.Parent = startNode;
 31                     OpenList.Add(curNode);
 32                 }
 33                 else
 34                 {  
 35                     //此节点在OpenList中
 36                     //若此节点的新估值g(x)小于之前的g(x),则更改g(x)的值,并重新赋值父节点
 37                     int newg = GetGValue(curNode, startNode)+startNode.G;
 38                     if (newg < curNode.G)
 39                     {
 40                         curNode.G = newg;
 41                         curNode.Parent = startNode;
 42                     }
 43                     //否则,不做操作
 44                 }
 45             }
 46 
 47             //4.若当前节点为目标节点则执行操作6
 48             if (startNode != endNode)
 49             {
 50                 //没有可走点却没找到终点,寻路失败
 51                 if (OpenList.Count == 0)
 52                 {
 53                     return new List<Node>();
 54                 }
 55 
 56                 Node nextNode = null;
 57                 //6.重复以上步骤
 58                 foreach (Node curNode in OpenList)
 59                 {
 60                     if (nextNode == null)
 61                     {
 62                         nextNode = curNode;
 63                     }
 64                     else if (nextNode.F >= curNode.F)
 65                     {
 66                         nextNode = curNode;
 67                     }
 68                 }
 69                 return FindWayByAStart(nextNode, endNode);
 70             }
 71             else
 72             {
 73                 //7.通过当前节点的父节点一层层往上遍历,得到目标路径节点的倒序排列.
 74                 List<Node> way = new List<Node>();
 75                 List<Node> backWay = new List<Node>();
 76                 Node curNode = startNode;
 77                 while (true)
 78                 {
 79                     backWay.Add(curNode);
 80 
 81                     if (curNode.Parent == null)
 82                     {
 83                         backWay.Remove(curNode);
 84                         backWay.Remove(startNode);
 85                         break;
 86                     }
 87                     else
 88                     {
 89                         curNode = curNode.Parent;
 90                     }
 91                 }
 92 
 93                 Node[] nodes = backWay.ToArray();
 94 
 95                 for (int i = nodes.Length - 1; i >= 0; i--)
 96                 {
 97                     way.Add(nodes[i]);
 98                 }
 99                 return way;
100             }
101    
102         }
103 
104         internal class Node
105         {
106             public int F {
107                 get { return G + H; }
108             }
109 
110             public int G;
111             public int H;
112 
113             public Node Parent;
114         }
115 
116         int GetGValue(Node a, Node b)
117         {
118             //TODO
119             return 0;
120         }
121 
122         int GetHValue(Node a, Node b)
123         {
124             //TODO
125             return 0;
126         }
127     }
128 }
View Code
原文地址:https://www.cnblogs.com/WongSiuming/p/5044670.html