练习题 贪吃蛇走迷宫 POJ1324

/*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 }

 

 

posted @ 2017-12-28 16:46  proscientist  阅读(490)  评论(0编辑  收藏  举报