HDOJ 1372

  国际象棋走马步,用A*算法A了,但用时挺长的,估计还是简单BFS快多了,代码也好写……

#include <cstdio>
#include <map>
#include <algorithm>
#include <cmath>

using namespace std;


typedef struct {
    int c_, n_;
} Position;


inline bool IsEqual(const Position &a, const Position &b)
{
    return a.c_ == b.c_ && a.n_ == b.n_;
}


inline bool IsLegal(const Position &pos)
{
    return pos.c_ >= 1 && pos.c_ <= 8 && pos.n_ >= 1 && pos.n_ <= 8;
}


typedef struct {
    int g_;
    int h_;
    int f_;
} Node;


struct PosComp {
    inline bool operator ()(const Position &a, const Position &b)
    {
        return a.c_ < b.c_ || (a.c_ == b.c_ && a.n_ < b.n_);
    }
};


typedef map<Position, Node, PosComp> Map;

int dir[8][2] = {
    1, 2,
    1, -2,
    2, 1,
    2, -1,
    -1, 2,
    -1, -2,
    -2, 1,
    -2, -1
};


int H(const Position &pos, const Position &dst)
{
    return (fabs(pos.c_ - dst.c_) + fabs(pos.n_ - dst.n_)) / 3;
}


inline void CalF(Node *node)
{
    node->f_ = node->g_ + node->h_;
}

typedef pair<Position, Node> Pair;

inline bool MapItComp(const Pair &a, const Pair &b)
{
    return a.second.f_ < b.second.f_;
}


int GetMinMovesCount(const Position &src, const Position &dst)
{
    Map open, close;
    Node src_n = {0};
    src_n.h_ = H(src, dst);
    CalF(&src_n);
    open[src] = src_n;

    while (!open.empty()) {
        Map::iterator it = min_element(open.begin(), open.end(), MapItComp);
        Position cur_pos = it->first;
        Node cur_node = it->second;
        if (IsEqual(cur_pos, dst)) {
            return cur_node.g_;
        }

        close[cur_pos] = cur_node;
        open.erase(it);

        for (int i=0; i<8; ++i) {
            Position next_pos = {
                cur_pos.c_ + dir[i][0], cur_pos.n_ + dir[i][1]
            };
            if (!IsLegal(next_pos)) continue;

            Node next_node;
            next_node.g_ = cur_node.g_ + 1;
            next_node.h_ = H(next_pos, dst);
            CalF(&next_node);

            Map::iterator oit = open.find(next_pos);
            if (oit != open.end() && oit->second.f_ <= next_node.f_) continue;

            Map::iterator cit = close.find(next_pos);
            if (cit != close.end() && cit->second.f_ <= next_node.f_) continue;

            open.erase(next_pos);
            close.erase(next_pos);
            open[next_pos] = next_node;
        }
    }

    return -1;
}


inline int C(char c)
{
    return c - 'a' + 1;
}

inline int N(char n)
{
    return n - '0';
}


int main()
{
    char src[3], dst[3];

    while (scanf("%s%s", src, dst) != EOF) {
        Position src_p = {C(src[0]), N(src[1])};
        Position dst_p = {C(dst[0]), N(dst[1])};
        printf("To get from %s to %s takes %d knight moves.\n", src, dst,
               GetMinMovesCount(src_p, dst_p));
    }

    return 0;
}

你可能感兴趣的:(OJ)