/*POJ 1324
题意:
给出一个n*m的贪吃蛇地图,以及贪吃蛇现在身体各个块所在的位置,求它的头走到(1,1)位置最少需要多少步。
其中蛇在移动的过程中不能走到障碍物上,也不能撞到自己的身体上。
题解:写迷宫问题首先应该避免死循环,即相同状态不能多次入队。本次搜索状态不仅有蛇头的位置还有蛇身的相对位置。
因为蛇身必然连贯,利用这点进行状态压缩,相对于上个点可以有4种方位。
可优化的地方:
由于vis数组很大,如果对于每个tc都初始化vis数组浪费时间,所以在申请了全局变量vis之后,我们对于每个tc,都只用当前的tc值去标记vis表示当前状态已出现。
*/
1 #include <stdio.h> 2 #define MAX 22 3 bool map[MAX][MAX],vis[MAX][MAX][16385]; 4 struct Node{ 5 int x, y, st, d; 6 }; 7 int bfs(int hy,int hx,int hst){ 8 if (hy == 1 && hx == 1)return 0; 9 for (int i = 0; i < MAX;++i) 10 for (int j = 0; j < MAX;++j) 11 for (int k = 0; k < 16384; ++k) 12 vis[i][j][k] = 0; 13 q.init(); 14 q.push(hy, hx, hst, 0); 15 vis[hy][hx][hst] = true; 16 while (!q.empty()){ 17 Node in = q.pop(); 18 int y = in.y, x = in.x, st = in.st, d = in.d; 19 for (int dn = 0; dn < 4; ++dn){ 20 int ny = y + dy[dn], nx = x + dx[dn]; 21 if (ny == 1 && nx == 1)return d + 1; 22 if (ny<1 || ny>N || nx<1 || nx>M || map[ny][nx] || isSnake(ny, nx, in))continue; 23 int nst = (st >> 2) + (((dn + 2) % 4) << (2 * (L - 2))); 24 if (vis[ny][nx][nst])continue; 25 q.push(ny, nx, nst, d + 1); 26 vis[ny][nx][nst] = true; 27 } 28 } 29 return -1; 30 } 31 int main(){ 32 int tc = 0, heady, headx, headst; 33 while (scanf("%d%d%d", &N, &M, &L) != EOF && N){ 34 headst = 0; 35 scanf("%d%d", &heady, &headx); 36 int ty, tx, prey = heady, prex = headx; 37 for (int i = 1; i < L; ++i){ 38 scanf("%d%d", &ty, &tx); 39 for (int dn = 0; dn < 4; ++dn){ 40 if (prey + dy[dn] == ty&&prex + dx[dn] == tx){ 41 headst = (headst << 2) + dn; 42 break; 43 } 44 } 45 prey = ty, prex = tx; 46 } 47 scanf("%d", &K); 48 int block_x, block_y; 49 for (block_x = 0; block_x < MAX; ++block_x) 50 for (block_y = 0; block_y < MAX; ++block_y) 51 map[block_x][block_y] = false; 52 for (int i = 0; i < K; ++i){ 53 scanf("%d%d", &block_x, &block_y); 54 map[block_x][block_y] = true; 55 } 56 printf("Case %d: %d\n", ++tc, bfs(heady, headx, headst)); 57 } 58 return 0; 59 } 60 61 struct Queue{ 62 Node nodepool[1200000];//3^6*4*20*20 / 4^7*400 63 Node *tnode; 64 int poolIndex, front, rear; 65 void init(){ 66 poolIndex = -1; 67 front = rear = 0; 68 } 69 void push(int y, int x, int st, int d){ 70 tnode = &nodepool[rear++]; 71 tnode->y = y, tnode->x = x, tnode->st = st, tnode->d = d; 72 } 73 Node pop(){ 74 Node ret = nodepool[front++]; 75 return ret; 76 } 77 bool empty(){ 78 return rear == front; 79 } 80 }q; 81 82 int dy[] = { 1, 0, -1, 0 };//下,左,上,右 83 int dx[] = { 0, -1, 0, 1 }; 84 85 bool isSnake(int findy, int findx, Node nd){ 86 int dir[10]; 87 for (int i = L - 1; i > 0; --i){ 88 dir[i] = nd.st & 3;//取低两位 89 nd.st >>= 2; 90 } 91 int y = nd.y, x = nd.x; 92 for (int i = 1; i < L; ++i){ 93 y += dy[dir[i]]; 94 x += dx[dir[i]]; 95 if (y == findy&&x == findx)return true; 96 } 97 return false; 98 }