poj 1324 Astar
/* 题意:贪吃蛇,求到(1,1)的最短路径 题解:A_star搜索 感觉不完全是A*,也许有更好的做法,估价函数为(x-1+y-1),比网上说的先用BFS搜索一遍求估价值要快=。= */ #include <cstdio> #include <cstring> #include <queue> int map[25][25]; int dir[4][2] = {-1,0,0,1,1,0,0,-1}; // 其中四个方向不可随意改变,因为在后面通过这一步来简化了一些东西 int n,m,l; struct position { int x,y; }; struct node { int x,y,depth,h; int body; bool operator < (const node &t) const { return h + depth > t.h + t.depth; } }; std::priority_queue<node>Q; int vis[21][21][1<<14]; bool is_passable(node t, int i) // 判断往i方向能否通行 { int nx = t.x + dir[i][0]; int ny = t.y + dir[i][1]; int px = t.x; int py = t.y; if (map[nx][ny] == -1) // 不是边界或者障碍物 return false; for(int j=1; j<l; j++) // 判断不是身体 { int c = t.body & 3; px -= dir[c][0]; py -= dir[c][1]; if (px == nx && py == ny) return false; t.body >>= 2; } return true; } int Astar(position head, int body) { while (!Q.empty()) Q.pop(); node tmp; tmp.x = head.x; tmp.y = head.y; tmp.depth = 0; tmp.h = tmp.x + tmp.y - 2; tmp.body = body; memset(vis,0,sizeof(vis)); Q.push(tmp); vis[tmp.x][tmp.y][tmp.body] = -1; while (!Q.empty()) { tmp = Q.top(); Q.pop(); if (1 == tmp.x && 1 == tmp.y) return tmp.depth; vis[tmp.x][tmp.y][tmp.body] = -1; for(int i=0; i<4; i++) { if (is_passable(tmp,i)) { int nx = tmp.x + dir[i][0],ny = tmp.y + dir[i][1]; int tbody = (tmp.body << 2) & ((1 << (2*(l-1)))-1); tbody += i; // dir数组的四个方向已经相对应,因此可以直接加 if (0 == vis[nx][ny][tbody]) // 已入队的即可跳过 { node vtmp; vtmp.x = nx; vtmp.y = ny; vtmp.depth = tmp.depth + 1; vtmp.h = vtmp.x + vtmp.y - 2; vtmp.body = tbody; vis[nx][ny][tbody] = -1; Q.push(vtmp); } } } } return -1; } int main(void) { int cas = 1; while (~scanf("%d%d%d",&n,&m,&l) && n+m+l) { position head; scanf("%d%d",&head.x,&head.y); int x,y,px,py; px = head.x; py = head.y; int body = 0; for(int i=1; i<l; i++) // body最高2位表示尾部 { scanf("%d%d",&x,&y); // 0~3分别表示从该点出发往上,右,下,左可以到达前面的点 if (x+1 == px) body += (2 << 2*(i-1)); else if (x-1 == px) body += 0; else if (y+1 == py) body += (1 << 2*(i-1)); else body += (3 << 2*(i-1)); px = x; py = y; } int k; scanf("%d",&k); memset(map,0,sizeof(map)); for(int i=1; i<=n; i++) map[i][0] = map[i][m+1] = -1; for(int i=1; i<=m; i++) map[0][i] = map[n+1][i] = -1; while (k--) { scanf("%d%d",&x,&y); map[x][y] = -1; } printf("Case %d: %d\n",cas,Astar(head, body)); cas++; } return 0; }