AT_abc339_d 题解
题意简述
棋盘上有两枚棋子,有些格子可以到达,有些不能,不能超出边界。
每次可以让两枚棋子朝相同的方向移动,若某个棋子的下一个位置不允许到达,则该棋子这次不会移动。求将两枚棋子移动到同一格
思路
考虑 bfs,因为
队列同时记录两个棋子的位置,然后记忆化一下,不走重复的状态。
然后按照题意模拟即可,如果某个棋子扩展出来的位置无法到达,那就让它保持不动就行。
Code
const int mx[4] = {0, 1, 0, -1}, my[4] = {1, 0, -1, 0};
struct Node{
int x1, y1, x2, y2, s;
};
int main()
{
cin >> n;
int x1 = 0, y1, x2, _y2;
memset(a, '#', sizeof a);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
cin >> a[i][j];
if (a[i][j] == 'P')
{
if (x1)
x2 = i, _y2 = j;
else
x1 = i, y1 = j;
}
}
f[x1][y1][x2][_y2] = true;
q.push({x1, y1, x2, _y2, 0});
while (!q.empty())
{
Node t = q.front();
q.pop();
if (t.x1 == t.x2 && t.y1 == t.y2)
{
printf("%d", t.s);
return 0;
}
for (int i=0;i<4;i++)
{
int nx1 = t.x1 + mx[i], ny1 = t.y1 + my[i];
int nx2 = t.x2 + mx[i], ny2 = t.y2 + my[i];
if (a[nx1][ny1] == '#')
nx1 = t.x1, ny1 = t.y1;
if (a[nx2][ny2] == '#')
nx2 = t.x2, ny2 = t.y2;
if (f[nx1][ny1][nx2][ny2])
continue;
f[nx1][ny1][nx2][ny2] = true;
q.push({nx1, ny1, nx2, ny2, t.s + 1});
}
}
puts("-1");
return 0;
}