码迷,mamicode.com
首页 > 其他好文 > 详细

A* Pathfinding Algorithm

时间:2015-06-28 06:22:58      阅读:121      评论:0      收藏:0      [点我收藏+]

标签:

Given? an ?n? x ?n ?grid ?with ?a ?person? and ?obstacles, ?how? would ?you ?find ?a? path ?for ?the? person? to? a? particular ?destination?? ?The ?person? is ?permitted? to? move ?left,?right,? up,? and? down.

Sample Input:

............
....oo..d...
....o.......
.p..oooo....
............

‘p‘ represents the start position, ‘o‘ a obstacle, d ‘ the destination.

Output: a optimal path from  ‘p‘ to ‘d‘ 

 

C++ Sample Code (using A* method to find a optimal path):

 

  1 #include <iostream>
  2 #include <vector>
  3 #include <unordered_set>
  4 #include <set>
  5 #include <string>
  6 #include <cstdlib>
  7 #include <climits>
  8 using namespace std;
  9 
 10 struct Point {
 11     int i, j;
 12     Point(int _i = -1, int _j = -1) : i(_i), j(_j) {}
 13 };
 14 
 15 int get_index(int cols, const Point& point) {
 16     return point.i * cols + point.j;
 17 }
 18 
 19 vector<Point> neighbor_points(vector<vector<char>>& grid, int index) {
 20     vector<Point> result;
 21     int rows = grid.size(), cols = grid[0].size();
 22     int i = index / cols, j = index % cols;
 23     int x[4], y[4];
 24     // 0: left, 1: right, 2: top, 3: bottom
 25     x[0] = i, x[1] = i, x[2] = i-1, x[3] = i+1;
 26     y[0] = j-1, y[1] = j+1, y[2] = j, y[3] = j;
 27     for (int k = 0; k < 4; k++) {
 28         if (x[k] >= 0 && x[k] < rows && y[k] >= 0 && y[k] < cols 
 29             && grid[x[k]][y[k]] != o) {
 30             result.push_back(Point(x[k], y[k]));
 31         }
 32     }
 33     return result;
 34 }
 35 
 36 int h_score_estimate(const Point& p1, const Point& p2) {
 37     return abs(p2.i - p1.i) + abs(p2.j - p1.j);
 38 }
 39 
 40 void print_path(int cols, int index, const vector<int>& parent) {
 41     if (index != -1) {
 42         print_path(cols, parent[index], parent);
 43         cout << "(" << index/cols << ", " << index%cols << ") ";
 44     }
 45 }
 46 
 47 class my_comp {
 48     const vector<int>& f_score;
 49 public:
 50     my_comp(const vector<int>& f_scr) : f_score(f_scr) {}
 51     bool operator() (const int i, const int j) const {
 52         if (f_score[i] != f_score[j]) {
 53             return f_score[i] < f_score[j];
 54         } else return i < j;
 55     }
 56 };
 57     
 58 void A_star(vector<vector<char>>& grid, const Point& person, const Point& destination) {
 59     int rows = grid.size();
 60     int cols = grid[0].size();
 61     int size = rows * cols;
 62     
 63     // cost form the start point along best known path
 64     vector<int> g_score(size, INT_MAX);    
 65     // estimate total cost from the start point to the destination through a point 
 66     vector<int> f_score(size, INT_MAX);  
 67     
 68     vector<int> parent(size, -1);
 69     
 70     set<int, my_comp> open_set((my_comp(f_score))); // the set of node to be evaluated
 71     unordered_set<int> closed_set; // the set of node evaluated
 72 
 73     int psn_index = get_index(cols, person);
 74     int dst_index = get_index(cols, destination);
 75 
 76     g_score[psn_index] = 0;
 77     f_score[psn_index] = h_score_estimate(person, destination);
 78     open_set.insert(psn_index);
 79     
 80     while (!open_set.empty()) {
 81         // get the point with minimal f_score in open_set
 82         int cur_index = *(open_set.begin());
 83         //cout << "curr : (" << cur_index/cols << ", " << cur_index%cols << ")" << endl; 
 84         if (cur_index == dst_index) {
 85             cout << "destination found !!!" << endl;
 86             print_path(cols, dst_index, parent);
 87             cout << endl;
 88             return;
 89         }
 90         
 91         // switch the current point from open_set to close_set
 92         open_set.erase(cur_index);
 93         closed_set.insert(cur_index);
 94 
 95         auto neighbors = neighbor_points(grid, cur_index);
 96         //cout << "no. of neighbors : " << neighbors.size() << endl; 
 97         for (auto& neighbor : neighbors) {
 98             //cout << "nbr : (" << neighbor.i << ", " << neighbor.j << ")" << endl;
 99             int nbr_index = get_index(cols, neighbor);
100             if (closed_set.count(nbr_index) != 0) continue;
101 
102             int tentative_g_score = g_score[cur_index] + 1 /*dist_between(current, neighbor)*/;
103             if (open_set.count(nbr_index) == 0 || tentative_g_score < g_score[nbr_index]) {
104                 parent[nbr_index] = cur_index;
105                 g_score[nbr_index] = tentative_g_score;
106                 f_score[nbr_index] = g_score[nbr_index] + h_score_estimate(neighbor, destination);
107                 if (open_set.count(nbr_index) != 0) {
108                     open_set.erase(nbr_index);
109                 }
110                 open_set.insert(nbr_index);
111             }
112         }
113     }
114     cout << "destination not found !!!" << endl;
115 }
116 
117 int main() {
118     vector<vector<char>> grid;
119     Point person, destination;
120     string line;
121     int i = 0;
122     while (getline(cin, line)) {
123         vector<char> row;
124         for (int j = 0; j < line.size(); j++) {
125             if (line[j] == p) {
126                 person = Point(i, j);
127             } else if (line[j] == d) {
128                 destination = Point(i, j);
129             }
130             row.push_back(line[j]);
131         }
132         //cout << line << endl;
133         grid.push_back(row);
134         i++;
135     }
136 
137     A_star(grid, person, destination);
138     return 0;
139 }

 

The output of the program with the sample input above:

destination found !!!
(3, 1) (2, 1) (1, 1) (1, 2) (1, 3) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (1, 8) 

 

The terminologies used in A* algorithm are described on Wikipedia (https://en.wikipedia.org/wiki/A*_search_algorithm). 

Summary of the A* Method (From http://www.policyalmanac.org/games/aStarTutorial.htm)

1) Add the starting square (or node) to the open list (open_set in my code).

2) Repeat the following:

a) Look for the lowest F (f_score) cost square on the open list. We refer to this as the current square.

b) Switch it to the closed list (close_set).

c) For each of the 8 squares adjacent to this current square …  (In the problem above, we just consider at most 4 neighbors)

  • If it is not walkable or if it is on the closed list, ignore it. Otherwise do the following.           

  • If it isn’t on the open list, add it to the open list. Make the current square the parent of this square. Record the F, G, and H costs of the square. 

  • If it is on the open list already, check to see if this path to that square is better, using G cost as the measure. A lower G cost means that this is a better path. If so, change the parent of the square to the current square, and recalculate the G and F scores of the square. If you are keeping your open list sorted by F score, you may need to resort the list to account for the change.

d) Stop when you:

  • Add the target square to the closed list, in which case the path has been found, or
  • Fail to find the target square, and the open list is empty. In this case, there is no path.   

3) Save the path. Working backwards from the target square, go from each square to its parent square until you reach the starting square. That is your path. 

 

A* Pathfinding Algorithm

标签:

原文地址:http://www.cnblogs.com/bestofme/p/4604995.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!