【题解+代码】 HDU1401 Solitaire

Solitaire HDU1401

双向BFS,HASH记录状态
代码都写了注释,可读性应该还行
写的有点长,有点挫
题目链接

#include <bits/stdc++.h>

using namespace std;

int dir[4][2] // 移动的方向
        {
                { 1, 0 },
                { 0, 1 },
                { -1, 0 },
                { 0, -1 }
        };

struct point
{
    int x, y;

    explicit point(int x = 0, int y = 0) : x(x), y(y) {}

    bool operator<(point p) // 重载小于号,排序用
    {
        if (this->x == p.x)
            return this->y < p.y;
        else
            return this->x < p.x;
    }

    bool operator==(point p) // 重载等于号,判断与其他点有没有重合用
    {
        return this->x == p.x && this->y == p.y;
    }
};

struct status
{
    int step;
    point p[4];

    status() {}

    status (int pos[8], int step)
    {
        for (int i = 0; i < 4; ++i)
        {
            this->p[i].x = pos[2 * i];
            this->p[i].y = pos[2 * i + 1];
        }
        this->step = step;
    }

    bool move(int index, int dx, int dy, status& nex) // 移动棋子,index代表移动第几个棋子,
    {                                                 // dxdy表示坐标偏移,nex用于储存移动后的状态
        nex = *this;
        point& mp = nex.p[index];

        mp.x += dx;
        mp.y += dy;
        nex.step++;

        if (nex.step > 4) // 一共最多走8步,那就初始状态走四步,最终状态走四步,看有没有重合
            return false;

        if (mp.x < 1 || mp.x > 8 || mp.y < 1 || mp.y > 8)
            return false;

        for (int i = 0; i < 4; ++i)
        {
            if (i != index && mp == nex.p[i]) // 有重合的情况,跳两格
            {
                mp.x += dx;
                mp.y += dy;
                break;
            }
        }

        return !(mp.x < 1 || mp.x > 8 || mp.y < 1 || mp.y > 8);
    }

    int getHash() // 用int表示状态,8位十进制整数,储存四个坐标,计算hash值前先对坐标进行排序,
    {             // 为了不打乱原来的棋子的顺序,先对数组进行排序
        point pp[4];
        for (int i = 0; i < 4; ++i)
            pp[i] = this->p[i];

        sort(pp, pp + 4);

        return pp[0].x + pp[0].y * (int)1e1 +
        pp[1].x * (int)1e2 + pp[1].y * (int)1e3 +
        pp[2].x * (int)1e4 + pp[2].y * (int)1e5 +
        pp[3].x * (int)1e6 + pp[3].y * (int)1e7;
    }
};

bool bfs(status src, status dst)
{
    if (src.getHash() == dst.getHash())
        return true;

    queue <status> q1;
    queue <status> q2;
    set <int> vis1; // set储存hash值,记录已经访问过的状态
    set <int> vis2;

    q1.push(src);
    q2.push(dst);
    vis1.insert(src.getHash());
    vis2.insert(dst.getHash());

    while (!q1.empty() || !q2.empty())
    {
        if (!q1.empty())
        {
            status now = q1.front();
            q1.pop();

            if (vis2.count(now.getHash()))
                return true;

            status nex;
            for (int i = 0; i < 4; ++i)
            {
                for (int j = 0; j < 4; ++j)
                {
                    if (now.move(i, dir[j][0], dir[j][1], nex)) // 计算下一个状态
                    {
                        if (vis1.count(nex.getHash()) == 0)
                        {
                            if (vis2.count(nex.getHash()))
                                return true;

                            q1.push(nex);
                            vis1.insert(nex.getHash());
                        }
                    }
                }
            }
        }

        if (!q2.empty())
        {
            status now = q2.front();
            q2.pop();

            if (vis1.count(now.getHash()))
                return true;

            status nex;
            for (int i = 0; i < 4; ++i)
            {
                for (int j = 0; j < 4; ++j)
                {
                    if (now.move(i, dir[j][0], dir[j][1], nex)) // 计算下一个状态
                    {
                        if (vis2.count(nex.getHash()) == 0)
                        {
                            if (vis1.count(nex.getHash()))
                                return true;

                            q2.push(nex);
                            vis2.insert(nex.getHash());
                        }
                    }
                }
            }
        }
    }

    return false;
}

int main()
{
    int pos1[8], pos2[8];

    while (cin >> pos1[0])
    {
        for (int i = 1; i < 8; ++i)
            cin >> pos1[i];
        for (int i = 0; i < 8; ++i)
            cin >> pos2[i];

        status src(pos1, 0), dst(pos2, 0);

        if (bfs(src, dst))
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_41429999/article/details/85346986