当前位置:   article > 正文

A* 搜索算法

A* 搜索算法

营救公主:

公主被魔王抓走了,王子需要拯救出美丽的公主。他进入了魔王的城堡,魔王的城堡是一座很大的迷宫。为了使问题简单化,我们假设这个迷宫是一个N*M的二维方格。迷宫里有一些墙,王子不能通过。王子只能移动到相邻(上下左右四个方向)的方格内,并且一天只能移动一步,就是说,如果王子在(x,y)一步只能移动到(x-1,y),(x+1,y),(x,y-1),(x,y+1)其中的一个位置上。地图由‘S’,‘P’,‘.’,‘*’四种符号构成,‘.’表示王子可以通过,‘*’表示墙,王子不能通过;'S'表示王子的位置;‘P’表示公主的位置;T表示公主存活的剩余天数,王子必须在T内到达公主的位置,才能救活公主。如下图所示:


上面是一个5*5的迷宫,红色箭头标识的是从S到P的一条路径。这条路径是最短的一条。如果题目中给的T是5的话,那么就无法救出公主。

实现一个算法,计算王子到达公主位置的天数,如果不可达,返回-1。

int get_min_step(char *map, int row, int col)

来自WIKI:

A*搜索算法,俗称A星算法。这是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法。
常用于游戏中的NPC的移动计算,或在线游戏的BOT的移动计算上。
该算法像Dijkstra算法一样,可以找到一条最短路径;也像BFS一样,进行启发式的搜索。
在此算法中,如果以 g(n)表示从起点到任意顶点n的实际距离,h(n)表示任意顶点n到目标顶点的估算距离,那么 A*算法的公式为:f(n)=g(n)+h(n)。 
这个公式遵循以下特性:
如果h(n)为0,只需求出g(n),即求出起点到任意顶点n的最短路径,则转化为单源最短路径问题,即Dijkstra算法
如果h(n)<=“n到目标的实际距离”,则一定可以求出最优解。而且h(n)越小,需要计算的节点越多,算法效率越低。


伪码:

function A*(start,goal)
     closedset := the empty set                 //已经被估算的节点集合    
     openset := set containing the initial node //将要被估算的节点集合
     came_from := empty map
     g_score[start] := 0                        //g(n)
     h_score[start] := heuristic_estimate_of_distance(start, goal)    //h(n)
     f_score[start] := h_score[start]            //f(n)=h(n)+g(n),由于g(n)=0,所以……
     while openset is not empty
         x := the node in openset having the lowest f_score[] value
         if x = goal
             return reconstruct_path(came_from,goal)
         remove x from openset
         add x to closedset
         foreach y in neighbor_nodes(x)  //foreach=for each
             if y in closedset
                 continue
             tentative_g_score := g_score[x] + dist_between(x,y)
 
             if y not in openset
                 add y to openset
 
                 tentative_is_better := true
             elseif tentative_g_score < g_score[y]
                 tentative_is_better := true
             else
                 tentative_is_better := false
             if tentative_is_better = true
                 came_from[y] := x
                 g_score[y] := tentative_g_score
                 h_score[y] := heuristic_estimate_of_distance(y, goal)
                 f_score[y] := g_score[y] + h_score[y]
     return failure
 
 function reconstruct_path(came_from,current_node)
     if came_from[current_node] is set
         p = reconstruct_path(came_from,came_from[current_node])
         return (p + current_node)
     else
         return current_node

根据伪码直译的C代码,无任何优化,VC测试可用,寻路范围较小,所以用数组,有待改造成链表。

  1. #include "stdafx.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #define MAX_ROW_NUM 20
  6. typedef struct tagCELL_INFO
  7. {
  8. int state; /* 0-road 1-wall 2-jessi 3-princess */
  9. int g_value;
  10. int h_value;
  11. int f_value;
  12. }CELL_INFO;
  13. typedef struct tagMAP_INO_ST
  14. {
  15. CELL_INFO cells[MAX_ROW_NUM * MAX_ROW_NUM];
  16. char open_list[MAX_ROW_NUM * MAX_ROW_NUM];
  17. char close_list[MAX_ROW_NUM * MAX_ROW_NUM];
  18. int came_from[MAX_ROW_NUM * MAX_ROW_NUM];
  19. int real_row;
  20. int real_col;
  21. int start_pos;
  22. int dst_pos;
  23. }MAP_INFO_ST;
  24. MAP_INFO_ST map_info;
  25. int min_step = 0;
  26. #define INVALID_NODE_VALUE 0xFFFFFF
  27. int xdebug = 1;
  28. #define xprintf if(xdebug)printf
  29. int open_set_is_empty()
  30. {
  31. int i;
  32. for(i = 0; i < (MAX_ROW_NUM * MAX_ROW_NUM); i++) {
  33. if (map_info.open_list[i] != 0) return 0;
  34. }
  35. return 1;
  36. }
  37. int estimate_of_distance(int start, int goal)
  38. {
  39. int x1, y1;
  40. int x2, y2;
  41. x1 = start/map_info.real_col;
  42. y1 = start%map_info.real_col;
  43. x2 = goal/map_info.real_col;
  44. y2 = goal%map_info.real_col;
  45. return abs(x1 - x2) + abs(y1 - y2);
  46. }
  47. int least_score_in_open_set()
  48. {
  49. int i;
  50. int min_idx = 0, min_f = INVALID_NODE_VALUE;
  51. for(i = 0; i < (MAX_ROW_NUM * MAX_ROW_NUM); i++) {
  52. if (map_info.open_list[i] != 0) {
  53. if (map_info.cells[i].f_value < min_f) {
  54. min_idx = i;
  55. min_f = map_info.cells[i].f_value;
  56. }
  57. }
  58. }
  59. return min_idx;
  60. }
  61. /* function reconstruct_path(came_from,current_node)
  62. if came_from[current_node] is set
  63. p = reconstruct_path(came_from,came_from[current_node])
  64. return (p + current_node)
  65. else
  66. return current_node
  67. */
  68. int reconstruct_path(int curr_node)
  69. {
  70. int p;
  71. int x = curr_node/map_info.real_col;
  72. int y = curr_node%map_info.real_col;
  73. min_step++;
  74. xprintf("%d(%d,%d) <-- ", curr_node, x, y);
  75. if (map_info.came_from[curr_node] != INVALID_NODE_VALUE) {
  76. p = reconstruct_path(map_info.came_from[curr_node]);
  77. return p + curr_node;
  78. } else
  79. return curr_node;
  80. }
  81. int neighbor_of_x(int start_pos, int offset)
  82. {
  83. int x,y;
  84. int pos;
  85. x = start_pos/map_info.real_col;
  86. y = start_pos%map_info.real_col;
  87. if (offset == 0) { // down cell
  88. if (x == map_info.real_row - 1) return -1;
  89. pos = (x + 1)*map_info.real_col + y;
  90. } else if (offset == 1) { // up cell
  91. if (x == 0) return -1;
  92. pos = (x - 1)*map_info.real_col + y;
  93. } else if (offset == 2) { // right cell
  94. if (y == map_info.real_col - 1) return -1;
  95. pos = x*map_info.real_col + y + 1;
  96. } else if (offset == 3) { // left cell
  97. if (y == 0) return -1;
  98. pos = x*map_info.real_col + y - 1;
  99. }
  100. if (map_info.cells[pos].state == 1) return -1;
  101. return pos;
  102. }
  103. int astart_run(int start_pos, int goal_pos)
  104. {
  105. int i;
  106. int x, y;
  107. int tentative_g_score;
  108. int tentative_is_better;
  109. // openset := set containing the initial node
  110. map_info.open_list[start_pos] = 1;
  111. // came_from := empty map
  112. for(i = 0; i < MAX_ROW_NUM * MAX_ROW_NUM; i++) {
  113. map_info.came_from[i] = INVALID_NODE_VALUE;
  114. }
  115. // set g/h/f of initial node
  116. map_info.cells[start_pos].g_value = 0;
  117. map_info.cells[start_pos].h_value = estimate_of_distance(start_pos, goal_pos);
  118. map_info.cells[start_pos].f_value = map_info.cells[start_pos].h_value;
  119. while(!open_set_is_empty()) {
  120. //x := the node in openset having the lowest f_score[] value
  121. x = least_score_in_open_set();
  122. xprintf("\r\n process mnode %d", x);
  123. if (x == goal_pos) {
  124. xprintf("\r\n reach the goal: ");
  125. return reconstruct_path(goal_pos);
  126. }
  127. //remove x from openset, add x to closedset
  128. map_info.open_list[x] = 0;
  129. map_info.close_list[x] = 1;
  130. //foreach y in neighbor_nodes(x)
  131. for( i = 0; i < 4; i++) {
  132. y = neighbor_of_x(x, i);
  133. if (y < 0) continue;
  134. xprintf("\r\n process snode %d", y);
  135. // if y in closedset
  136. if (map_info.close_list[y]) continue;
  137. //tentative_g_score := g_score[x] + dist_between(x,y)
  138. tentative_g_score = map_info.cells[x].g_value + 1;
  139. if (!map_info.open_list[y]) {
  140. map_info.open_list[y] = 1;
  141. tentative_is_better = 1;
  142. } else if (tentative_g_score < map_info.cells[y].g_value) {
  143. tentative_is_better = 1;
  144. } else {
  145. tentative_is_better = 0;
  146. }
  147. if (tentative_is_better) {
  148. // came_from[y] := x
  149. map_info.came_from[y] = x;
  150. map_info.cells[y].g_value = tentative_g_score;
  151. map_info.cells[y].h_value = estimate_of_distance(y, goal_pos);
  152. map_info.cells[y].f_value = map_info.cells[y].g_value + map_info.cells[y].h_value;
  153. }
  154. }
  155. }
  156. return -1;
  157. }
  158. int get_min_step(char *map, int row, int col)
  159. {
  160. int i, j, pos;
  161. memset(&map_info, 0, sizeof(MAP_INFO_ST));
  162. map_info.real_row = row;
  163. map_info.real_col = col;
  164. for(i = 0; i < row; i++) {
  165. for(j = 0; j < col; j++) {
  166. pos = i*map_info.real_col + j;
  167. if ('.' == map[pos]) {
  168. map_info.cells[pos].state = 0;
  169. } else if ('*' == map[pos]) {
  170. map_info.cells[pos].state = 1;
  171. } else if ('S' == map[pos]) {
  172. map_info.cells[pos].state = 2;
  173. map_info.start_pos = pos;
  174. } else if ('P' == map[pos]) {
  175. map_info.cells[pos].state = 3;
  176. map_info.dst_pos = pos;
  177. } else {
  178. return -1;
  179. }
  180. }
  181. }
  182. min_step = 0;
  183. astart_run(map_info.start_pos, map_info.dst_pos);
  184. return min_step - 1;
  185. }
  186. int _tmain(int argc, _TCHAR* argv[])
  187. {
  188. int i,j;
  189. char map_input1[4][4] = {'.','.','.','.',
  190. '.','.','.','.',
  191. '.','.','.','.',
  192. 'S','*','*','P'};
  193. char map_input2[9][9] = { '.','S','.','.','.','.','.','.','.',
  194. '.','*','*','.','.','.','.','.','.',
  195. '.','.','.','*','*','.','.','.','.',
  196. '*','*','*','.','.','*','.','.','.',
  197. '.','.','.','.','.','.','*','.','.',
  198. '.','.','.','.','.','.','.','.','.',
  199. '.','.','.','.','.','.','.','*','*',
  200. '.','.','.','.','*','*','*','.','.',
  201. '.','.','.','.','.','.','P','.','.',};
  202. int result;
  203. result = get_min_step(&map_input1[0][0], 4, 4);
  204. printf("\r\n result=%d", result);
  205. result = get_min_step(&map_input2[0][0], 9, 9);
  206. printf("\r\n result=%d", result);
  207. return 0;
  208. }



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/558837
推荐阅读
相关标签
  

闽ICP备14008679号