POJ-1324 Holedox Moving 解题报告
Apr 13, 2016 • 🍻 03min 51s read
🔖 acmbfs图论状态压缩解题报告
题意简述
¶在一个
贪吃蛇的移动规则如下:
- 只能朝边相邻的格子移动
- 不能朝障碍物移动(身体及四周墙壁都视作障碍物)
数据范围:
题目简析
¶为方便叙述,对贪吃蛇的身体进行编号:蛇头为
- 蛇头用一个二元组
表示其位置 - 身体其它部分
用一个整数 来表示它相对 的方向。
注意到方向只有
约定第
两位 bit 表示蛇身第 号部分相对于 号部分的方向。当蛇头朝某一合法位置移动后,
其中, 表示移动后的蛇身位置关系, 为此次蛇头移动的方向 [1]。
所以,当贪吃蛇移动一步后,我们仅需将方向变量:左移两位,再右移两位,再或上蛇头移动的方向。剩下的问题就是宽度优先搜索了。
TIP
问题的难点在于记录移动的状态。
复杂度分析
¶由于移动操作仅需
空间复杂度
时间复杂度
AC 代码:
poj.1324.cpp | 96 lines.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596#include <algorithm>#include <cstdio>#include <cstring>#include <iostream>#include <queue>using namespace std;
const int nx[] = { -1, 0, 1, 0 };const int ny[] = { 0, 1, 0, -1 };
int T_T, N, M, L, B, bit, sx, sy, sd;bool vis[21][21][1 << 14 | 1], blank[21][21];
struct node { int x, y, d, s; node(int x = 0, int y = 0, int d = 0, int s = 0) : x(x), y(y), d(d), s(s) { } bool block(int x, int y) { if (x >= 1 && y >= 1 && x <= N && y <= M && blank[x][y]) { int mx = this->x; int my = this->y; int md = this->d; for (int i = 1; i < L; ++i) { int d = md & 3; mx += nx[d]; my += ny[d]; md >>= 2; if (mx == x && my == y) return true; } return false; } return true; }};
queue<node> Q;
int bfs() { while (!Q.empty()) Q.pop(); Q.push(node(sx, sy, sd)); vis[sx][sy][sd] = true;
while (!Q.empty()) { node now = Q.front(); Q.pop();
if (now.x == 1 && now.y == 1) return now.s; for (int d = 0; d < 4; ++d) { int mx = now.x + nx[d]; int my = now.y + ny[d]; if (!now.block(mx, my)) { int md = ((now.d << 2) & bit) | (d ^ 2); if (vis[mx][my][md]) continue; vis[mx][my][md] = true; Q.push(node(mx, my, md, now.s + 1)); } } }
return -1;}
void work() { while (scanf("%d%d%d", &N, &M, &L) == 3 && N && M && L) { bit = (1 << (L - 1 << 1)) - 1; for (int n = 1; n <= N; ++n) for (int m = 1; m <= M; ++m) memset(vis[n][m], 0, bit + 1); memset(blank, 1, sizeof blank);
scanf("%d%d", &sx, &sy); sd = 0; int mx = sx, my = sy, mu, mv; for (int i = 0; i < L - 1; ++i) { scanf("%d%d", &mu, &mv); for (int d = 0; d < 4; ++d) if (mx + nx[d] == mu && my + ny[d] == mv) { sd |= d << (i << 1); mx = mu; my = mv; break; } } scanf("%d", &B); while (B--) { scanf("%d%d", &mu, &mv); blank[mu][mv] = false; }
printf("Case %d: %d\n", ++T_T, bfs()); }}
int main() { work(); return 0;}
Related
¶