这题昨天开始做的...因为从来没有做过状态压缩.这是第一次接触.关于这个题没什么好说的,但是...好歹是俺迈出的第一步呐(=@__@=)~~~
昨天写了一遍,写了200行,加上调试的中转代码,膨胀到了6K...我去.后来调了一晚上终于发现了程序的一个bug:在去重时,忽略了蛇身的状态,只关联到了蛇头.
改完以后...果断TLE.昨天的代码用的是5进制数,第一内存爆得厉害,第二用vector数组作为返回对象,多重调用时时间消耗太严重.后来改写4进制,在状态转移时
直接用位运算操作加速.但是还是有各种没用过碰到的问题.今天终于调试成功了.虽然刚开始是WA.但是很快意识到在判断是否为终点时忽略了蛇头一开始就
在终点的数据.改完后TLE,感觉queue和vector耗时太严重,但是queue这部分用数组其实不太好,除非用数组循环.否则极容易越界.于是改了vector部分.删掉了
operator=部分的拷贝和return value.加速效果还是不错的,至少让我AC了( ⊙o⊙ )哇....这题可以双向广搜也可以A*但是我都不会...呵呵...
留下我翔一般的代码作个纪念:
41584K/2375MS
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
static int BIT = 0xffffff;
const int MAX = 25;
const int MAXN = 1<<16;
bool vis[MAX][MAX][MAXN];
bool Map[MAX][MAX];
/*
00(N)
11(W) 01(E)
10(S)
*/
int Move[4][2] = {-1,0, 0,1, 1,0, 0,-1};
struct Point {
int x, y;
Point(){}
Point(int a, int b):x(a), y(b){}
bool operator==(const Point& B)const {
return x == B.x && y == B.y;
}
};
vector<Point> point(MAX);
struct Node:public Point {
int x, y;
int status;
int steps;
Node(){}
Node(int a, int b):x(a),y(b){}
bool operator==(const Node& B)const {
return x == B.x && y == B.y;
}
bool operator==(const Point& B)const {
return x == B.x && y == B.y;
}
}now, next, E(1,1);
int n, m, L, K;
vector<Point> V(MAX);
void decode(int x, int y, int status) {
//printf("decode %d\n", status);
V[0] = (Point){x,y}; //snake.push_back((Point){x, y});
for (int i = 1; i < L; ++i) {
int dir = status&3;
status >>= 2;
x += Move[dir][0], y += Move[dir][1];
//printf("%d,%d\n", x, y);
V[i] = (Point){x,y}; //snake.push_back((Point){x,y});
}
/* **************/
//for (int i = 0; i < L; ++i) {
//printf("%d,%d\n", snake[i].x, snake[i].y);
//}
//getchar();
//return snake;
}
int encode(void) {
int status = 0, x, y, now;
for (int i = L-1; i > 0; --i) {
x = point[i].x - point[i-1].x;
y = point[i].y - point[i-1].y;
if (!x) {
now = (y^1) ? 3 : 1;
} else {
now = (x^1) ? 0 : 2;
}
status <<= 2;
status |= now;
}
//printf("status = %d\n", status);
return status;
}
void init(void) {
BIT = 0;
for (int i = 1; i < L; ++i) {
BIT <<= 2;
BIT |= 3;
}
//printf("%d\n", BIT);
memset(vis, false, sizeof(vis));
now.x = point[0].x, now.y = point[0].y;
now.steps = 0;
now.status = encode();
//printf("init: now = %d,%d,%d\n", now.x, now.y, now.status);
}
/* 判断next是否合法 */
bool judge(void) {
if (next.x <= 0 || next.y <= 0
|| next.x > n || next.y > m || !Map[next.x][next.y]) return false;
//printf("next = %d,%d\n", next.x, next.y);
for (int i = 0; i < L; ++i) {
//printf("ex:%d,%d\n", V[i].x, V[i].y);
if (next == V[i]) return false;
}
//getchar();
return true;
}
int BFS(void) {
init();
queue<Node> Q;
Q.push(now);
vis[now.x][now.y][now.status] = true;
while (!Q.empty()) {
now = Q.front(); Q.pop();
if (now == E) return now.steps;
decode(now.x, now.y, now.status);
//cout << "now = " << now.x << ", " << now.y << ", " << now.status << endl;
for (int i = 0; i < 4; ++i) {
/* 对龟头来说,有四个方向可以钻,当然,不能搞到自己身子, */
/* 所以三个方向 */
//printf("now = %d,%d,%d\n", now.x, now.y, now.steps);
next.x = now.x + Move[i][0];
next.y = now.y + Move[i][1];
next.steps = now.steps + 1;
//printf("next = %d,%d,%d\n", next.x, next.y, next.steps);getchar();
if (!judge()) continue;
next.status = (now.status<<2)&BIT;
next.status |= (i+2)%4;
if (vis[next.x][next.y][next.status]) continue;
vis[next.x][next.y][next.status] = true;
next.steps = now.steps + 1;
//if (next == E) return next.steps;
//printf("Push%d: %d,%d,%d,%d\n", i, next.x, next.y, next.steps, next.status);
Q.push(next);
}
}
return -1;
}
int main() {
static int cas = 0;
while (~scanf(" %d %d %d", &n, &m, &L) && L) {
memset(Map, true, sizeof(Map));
for (int i = 0; i < L; ++i) {
scanf(" %d %d", &point[i].x, &point[i].y);
}
scanf(" %d", &K);
int x, y;
for (int i = 0; i < K; ++i) {
scanf(" %d %d", &x, &y);
Map[x][y] = false;
}
printf("Case %d: %d\n", ++cas, BFS());
}
return 0;
}