POJ 2243 Knight Moves A*

来源:互联网 发布:大数据的书 编辑:程序博客网 时间:2024/05/29 19:09

题意:

象棋中马从一个格子到另一个格子最少需要多少步

思路:

简单BFS,主要用此题练习了A*算法

A*算法,原理同BFS,只是通过启发式函数(代码中的f,为起点到该点的代价g和该点到终点的股价h的和)来进行BFS的剪枝。

源码:

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <iostream>

#include <queue>

using namespace std;

#define ABS(a) (((a)>0)?(a):(-(a)))///abs,注意每个a都需要括号,总的还需要一个括号

int vis[10][10];

char str[10];

int dx[] = {-1,-2,-2,-1,1,2,2,1};///方向

int dy[] = {-2,-1,1,2,2,1,-1,-2};

int x1,x2,y1,y2,ans;///初始坐标和目的坐标,答案

struct D

{

    int x,y,step;

    int f,g,h;

    D(){step = 0;}

    D(int _x,int _y,int _step,int _f,int _g,int _h){x = _x,y = _y,step = _step;f = _f;g = _g;h = _h;}

    bool operator < (const D &a)const{return f > a.f;}///在优先队列,符号需要相反,比如小的在前需要f>a.f

};///fgh分别表示启发式函数和,从初始点到此点代价,从此点到终点股价

priority_queue<D> que;///优先队列实现

int haminton(int x,int y)///曼哈顿距离

{

//    printf("x = %d,y = %d,x2 = %d,y2 = %d\n",x,y,x2,y2);

    int ans = ABS(x - x2) + ABS(y - y2);

//    printf("ans = %d\n\n",ans);

    return ans * 10;

}

bool valid(int x,int y)

{

    if(x < 0 || x > 7)

        return false;

    if(y < 0 || y > 7)

        return false;

    return true;

}

int main()

{

    while(gets(str) != NULL){

        x1 = str[0] - 'a';

        y1 = str[1] - '1';

        x2 = str[3] - 'a';

        y2 = str[4] - '1';

        while(!que.empty())

            que.pop();

        if(x1 == x2 && y1 == y2){

            ans = 0;

        }

        else{

            memset(vis, 0, sizeof(vis));

            vis[x1][y1] = 1;

            D temp = D(x1,y1,0,haminton(x1,y1),0,haminton(x1,y1));

            que.push(temp);

            ans = -1;

            while(!que.empty()){

                temp = que.top();

                que.pop();

                int x = temp.x;

                int y = temp.y;

                int step = temp.step;

                int g = temp.g;

                int h = temp.h;

//                printf("x = %d,y = %d,step = %d,f = %d,g = %d,h = %d\n",x,y,step,temp.f,g,h);

                if(x == x2 && y == y2){

                    ans = step;

                    break;

                }

                for(int i=0; i<8; i++){

                    int tx = x + dx[i];

                    int ty = y + dy[i];

                    int tstep = step + 1;

                    if(!valid(tx,ty) || vis[tx][ty] == 1)

                        continue;

                    vis[tx][ty] = 1;

                    int tg = 23 + g;

                    int th = haminton(tx,ty);

                    temp = D(tx,ty,tstep,tg+th,tg,th);

                    que.push(temp);

                }

            }

        }

        printf("To get from %c%c to %c%c takes %d knight moves.\n",str[0],str[1],str[3],str[4],ans);

    }

    return 0;

}

 

0 0