双向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;
}
}