题目:二维推箱子游戏,给你箱子、人和目标的位置,输出问题的解(推箱子和行走的路径)。
分析:搜索、优先队列。优先顺序为:首先保证推箱子的字数最少、然后是走的步数最少。
利用二叉堆做优先队列,在上面进行bfs即可。
搜索状态为:木块坐标+人的坐标,即一个四元组S(X,Y,x,y);
每次(x,y)可以转化成周围四格位置,如果此时箱子在人的旁边,箱子能被推动,两者同向移动。
说明:注意搜索时按照字典序方向枚举,不然会WA╮(╯▽╰)╭。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
char maps[20][21];
typedef struct node0
{
int X,Y,x,y;
int front,push,move,id;
char step;
}dnode;
dnode H[160001];
dnode Q[160001];
bool U[20][20][20][20];
int dxy[4][2] = {0,1,-1,0,1,0,0,-1};
char O[5] = "ENSW",o[5] = "ensw";
int q_size;
//banery_heap define
int bh_size;
void bh_init()
{
bh_size = 0;
}
int bh_empty()
{
return bh_size == 0;
}
bool bh_cmp(dnode a, dnode b)
{
if (a.push != b.push)
return a.push < b.push;
return a.move < b.move;
}
void bh_insert(dnode s)
{
H[++ bh_size] = s;
int now = bh_size;
while (now > 1 && bh_cmp(H[now], H[now>>1])) {
swap(H[now], H[now>>1]);
now = now>>1;
}
}
dnode bh_delete(void)
{
swap(H[bh_size], H[1]);
int now = 1;
while (1) {
int New = now,L = (now<<1),R = (now<<1)+1;
if (L < bh_size && bh_cmp(H[L], H[New])) New = L;
if (R < bh_size && bh_cmp(H[R], H[New])) New = R;
if (now == New) break;
swap(H[now], H[New]);
now = New;
}
return H[bh_size --];
}
//banery_heap end
void output(dnode s)
{
if (s.front) {
output(Q[s.front]);
printf("%c",s.step);
}else printf("%c",s.step);
}
void bfs(dnode s, int n, int m)
{
memset(U, 0, sizeof(U));
U[s.X][s.Y][s.x][s.y] = 1;
q_size = 0;
bh_init();
bh_insert(s);
while (!bh_empty()) {
dnode New,now = bh_delete();
Q[q_size ++] = now;
for (int k = 0 ; k < 4 ; ++ k) {
New = now;
New.x += dxy[k][0];
New.y += dxy[k][1];
New.front = q_size-1;
if (New.x < 0 || New.x >= n || New.y < 0 || New.y >= m)
continue;
//推箱子
if (New.X == New.x && New.Y == New.y) {
New.X += dxy[k][0];
New.Y += dxy[k][1];
if (New.X < 0 || New.X >= n || New.Y < 0 || New.Y >= m)
continue;
if (maps[New.X][New.Y] != '#' && !U[New.X][New.Y][New.x][New.y]) {
New.step = O[k];
New.push ++;
if (maps[New.X][New.Y] == 'T') {
output(New);
return;
}
U[New.X][New.Y][New.x][New.y] = 1;
bh_insert(New);
}
}else if (maps[New.x][New.y] != '#' && !U[New.X][New.Y][New.x][New.y]) {
New.step = o[k];
New.move ++;
U[New.X][New.Y][New.x][New.y] = 1;
bh_insert(New);
}
}
}
printf("Impossible.");
}
int main()
{
int n,m,t = 1;
while (~scanf("%d%d",&n,&m) && n && m) {
for (int i = 0 ; i < n ; ++ i)
scanf("%s",maps[i]);
dnode s;
for (int i = 0 ; i < n ; ++ i)
for (int j = 0 ; j < m ; ++ j) {
if (maps[i][j] == 'S') {
s.x = i; s.y = j;
}
if (maps[i][j] == 'B') {
s.X = i; s.Y = j;
}
}
printf("Maze #%d\n",t ++);
bfs(s, n, m);
printf("\n\n");
}
return 0;
}