题意:给出棋盘的起始态和终结态,问能否在8步之内使得起始态变成终结态。
思路:简单的搜索题目,关键是如何保存棋盘的状态,我这里是利用了进制压缩进行保存的。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define N (1<<24)
struct Po {
int x, y;
bool operator<(const Po a) const{
if (x == a.x) return y < a.y;
return x < a.x;
}
};
struct P {
Po A[4];
}s, e;
queue<P>Q;
queue<int>step;
bool F[10][10];
bool flag[N+10];
int ci[8], end, go[4][2] = {1,0, -1,0, 0,1, 0,-1};
int mark[8][8];
int tr(P a) {
int re = 0, i;
sort(a.A, a.A+4);
for (i = 0;i < 4;i++) {
re += a.A[i].x*ci[i*2]+a.A[i].y*ci[i*2+1];
}
return re;
}
bool ch(int x, int y) {
return x < 0 || x >= 8 || y < 0 || y >= 8;
}
bool bfs() {
while (!Q.empty()) Q.pop();
while (!step.empty()) step.pop();
memset(flag, false, sizeof(flag));
Q.push(s);
step.push(0);
flag[tr(s)] = true;
int st, i, j, tx, ty, ca = 1, tt;
P v;
memset(mark, 0, sizeof(mark));
while (!Q.empty()) {
v = Q.front();
tt = step.front();
step.pop();
Q.pop();
st = tr(v);
if (st == end) return true;
if (tt == 8) continue;
ca++;
for (i = 0;i < 4;i++) {
mark[v.A[i].x][v.A[i].y] = ca;
}
for (i = 0;i < 4;i++) {
for (j = 0;j < 4;j++) {
tx = v.A[i].x+go[j][0], ty = v.A[i].y+go[j][1];
if (ch(tx, ty)) continue;
P tm = v;
if (mark[tx][ty] != ca) {
tm.A[i].x = tx, tm.A[i].y = ty;
}else {
tx += go[j][0], ty += go[j][1];
if (ch(tx, ty) || mark[tx][ty] == ca) continue;
tm.A[i].x = tx, tm.A[i].y = ty;
}
int tmst = tr(tm);
if (flag[tmst]) continue;
Q.push(tm), step.push(tt+1), flag[tmst] = true;
}
}
}
return false;
}
int main() {
int i, j, x, y;
ci[0] = 1;
for (i = 1;i < 8;i++) ci[i] = ci[i-1]*8;
while (~scanf("%d%d", &s.A[0].x, &s.A[0].y)) {
memset(F, false, sizeof(F));
for (i = 1;i < 4;i++) {
scanf("%d%d", &s.A[i].x, &s.A[i].y);
}
for (i = 0;i < 4;i++) s.A[i].x--, s.A[i].y--;
for (i = 0;i < 4;i++) {
scanf("%d%d", &x, &y);
e.A[i].x = x-1, e.A[i].y = y-1;
}
end = tr(e);
if (bfs()) puts("YES");
else puts("NO");
}
}