http://acm.fzu.edu.cn/problem.php?pid=2180
Time Limit: 5000 mSec Memory Limit : 32768 KB
Problem Description
在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士,
且有一个空位。在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上。给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘:
为了体现出骑士精神,他们必须以最少的步数完成任务。
Input
第一行有一个正整数T(T<=10) 表示一共有T组数据
接下来有T个5*5的矩形。0表示白色骑士1表示黑色骑士,*表示空位。(每组数据间有空行)
Output
对每组数据都输出一行。如果能在15步以内(包括15)到达目标状态,则输出步数,否则输出“Bored!”没有引号。
Sample Input
2
10110
01*11
10111
01001
0000001011
110*1
01110
01010
00100
Sample Output
7
Bored!
思路
双向BFS+状态压缩
PS:map使用自定义类型要重载‘<’运算符,否则无法正常进行查找等操作
代码
#include <cstdio>
#include <queue>
#include <map>
using namespace std;
int T, dir[8][2] = { 2, 1, 1, 2, -2, -1, -1, -2, 2, -1, -2, 1, 1, -2, -1, 2 };
struct Elem
{
Elem(int g, int x, int y, int st) : G(g), sx(x), sy(y), step(st) { }
bool operator== (const Elem& e) const { return this->G == e.G && this->sx == e.sx && this->sy == e.sy; }
bool operator< (const Elem& e) const { return this->G == e.G ? this->sx == e.sx ? this->sy < e.sy : this->sx < e.sx : this->G < e.G; }
int G, sx, sy, step;
};
Elem ed(549855, 2, 2, 0); // 0000010000110001111011111
int bfs(Elem st)
{
queue<Elem> Qst, Qed;
map<Elem, int> visST, visED; // [G] = step
Qst.push(st);
Qed.push(ed);
visST[st] = 0;
visED[ed] = 0;
while (!Qst.empty() && !Qed.empty())
{
Elem nst = Qst.front();
Qst.pop();
if (nst.step >= 8)
return -1;
for (int k = 0; k < 8; k++)
{
int nx = nst.sx + dir[k][0], ny = nst.sy + dir[k][1];
if (nx < 0 || nx >= 5 || ny < 0 || ny >= 5)
continue;
Elem next(nst.G, nx, ny, nst.step + 1);
if (nst.G & (1 << (nx * 5 + ny)))
next.G |= (1 << (nst.sx * 5 + nst.sy)), next.G ^= (1 << (nx * 5 + ny));
if (visST.find(next) == visST.end())
{
if (visED.find(next) != visED.end())
return next.step + visED[next];
Qst.push(next);
visST[next] = next.step;
}
}
Elem ned = Qed.front();
Qed.pop();
if (ned.step >= 8)
return -1;
for (int k = 0; k < 8; k++)
{
int nx = ned.sx + dir[k][0], ny = ned.sy + dir[k][1];
if (nx < 0 || nx >= 5 || ny < 0 || ny >= 5)
continue;
Elem next(ned.G, nx, ny, ned.step + 1);
if (ned.G & (1 << (nx * 5 + ny)))
next.G |= (1 << (ned.sx * 5 + ned.sy)), next.G ^= (1 << (nx * 5 + ny));
if (visED.find(next) == visED.end())
{
if (visST.find(next) != visST.end())
return next.step + visST[next];
Qed.push(next);
visED[next] = next.step;
}
}
}
return -1;
}
int main()
{
scanf("%d", &T);
while (T--)
{
Elem st(0, 0, 0, 0);
for (int i = 0; i < 5; i++)
{
getchar();
for (int j = 0; j < 5; j++)
{
char ch;
scanf("%c", &ch);
if (ch == '1')
st.G = st.G | (1 << (i * 5 + j));
else if (ch == '*')
st.sx = i, st.sy = j;
}
}
getchar();
if (st == ed)
printf("0\n");
else
{
int ans = bfs(st);
if (ans == -1 || ans > 15)
printf("Bored!\n");
else
printf("%d\n", ans);
}
}
}