例题解释A*
题目链接:
http://poj.org/problem?id=2243
题目意思很简单,一个8*8的棋盘,给定两个点的坐标,问国际象棋里面的骑士从一个点走到另一个点所需要的最小步数。走的方式就是类似于中国象棋里面的马,八个方位。
一般就会直接使用BFS搜了,8*8直接搜也不会爆,现在看下使用A*。
A*的关键是怎么选取一个合适的h(x),那就是需要保证:h( x ) <= d( x, y ) + h( y ),至于原因,参见:http://www.cnblogs.com/be-saber/p/4780564.html
对于一步的走法,那就是一个“日”字了。
这时我们就可以选择 欧几里得距离, 可以发现, h( x ), d(x, y), h(y)就是三角形的三边(可能三点共线)了,那么上述条件是肯定满足的了。
代码如下:
1 #include<cstdio>
2 #include<iostream>
3 #include<queue>
4 #include<cmath>
5 #include<algorithm>
6 #include<cstring>
7 using namespace std ;
8
9 #define POS pair<int, int>
10 const int MAXM = 10 ;
11 //h(x)取欧几里得距离
12 POS s, t ;
13 bool vis[MAXM][MAXM] ;
14 float gx[MAXM][MAXM] ;
15 int step[MAXM][MAXM] ;
16 int dir[8][2] = {{1, 2}, {1, -2}, {-1, 2}, {-1, -2}, {2, 1}, {2, -1}, {-2, 1}, {-2, -1}} ;
17 //
18 bool judge(POS x){
19 if( x.first < 1 || x.first > 8 || x.second < 1 || x.second > 8 ) return false ;
20 return true ;
21 }
22 //
23 float calDis(POS x, POS y){
24 return sqrt((x.first-y.first)*(x.first-y.first)+(x.second-y.second)*(x.second-y.second)) ;
25 }
26 //
27 int solve(){
28 memset(vis, false, sizeof(vis)) ;
29 memset(gx, 0, sizeof(gx)) ;
30 memset(step, 0, sizeof(step)) ;
31 priority_queue< pair<float, POS> > heap ;
32 while( !heap.empty() ) heap.pop() ;
33 heap.push(make_pair(-calDis(s, t), s)) ;
34 gx[s.first][s.second] = 0 ;
35 while( !heap.empty() ){
36 int val = heap.top().first ;
37 POS x = heap.top().second ;
38 heap.pop() ;
39 vis[x.first][x.second] = true ;
40 if( x.first == t.first && x.second == t.second ){
41 return step[x.first][x.second] ;
42 }
43 for( int i = 0; i < 8; i++ ){
44 POS u ;
45 u.first = x.first + dir[i][0], u.second = x.second + dir[i][1] ;
46 if( judge(u) && !vis[u.first][u.second] ){
47 gx[u.first][u.second] = gx[x.first][x.second] + sqrt(5) ;
48 heap.push(make_pair(-gx[u.first][u.second]-calDis(u, t), u)) ;
49 step[u.first][u.second] = step[x.first][x.second] + 1 ;
50 }
51 }
52 }
53 return 0 ;
54 }
55 //
56 int main(){
57 ////////freopen("1234.txt", "r", stdin) ;
58 char a, b, c, d ;
59 while( scanf("%c%c %c%c\n", &a, &b, &c, &d) != EOF ){
60 s = make_pair(a-'a'+1, b-'0') ;
61 t = make_pair(c-'a'+1, d-'0') ;
62 int step = solve() ;
63 printf("To get from %c%c to %c%c takes %d knight moves.\n", a, b, c, d, step) ;
64 }
65 return 0 ;
66 }