Total Submissions: 58 (15 users) Accepted: 24 (10 users)
[ My Solution ]
推箱子是个家喻户晓的游戏, 相信在大家小的时候都一定玩过。当然, 我们在这里还是做个简单介绍, 如下图所示, 游戏玩家初始站在地图的某个位置, 游戏目标是将图中的箱子全部移往目的地(下图’X’的位置), 每次移动只能选择上下左右方向上某个方向移动一格, 若移动的方向上有箱子存在, 则箱子也往相同的方向移动一格, 并且, 在移动过程中, 玩家(和箱子)不能穿越(或停留于)箱子、障碍物(下图树的位置)和边界区域的位置。除此之外, 为了尽可能的得到最高分, 玩家还应该以尽可能少的步数完成任务。
为了简化问题, 现在, 给你一个地图, 且地图上的游戏者、箱子和目的地都各只有一个, 你需要求出最少需要多少步才能完成任务呢?
输入的第一行有2个整数n, m (2 <= n, m <= 30), 接下来有n行, 每行有m个只由'.' , '*' , 'P', 'B', 'E' 构成的字符, 其中, ‘.’表示可通行区域, '*' 表示障碍物, 'P'表示玩家, 'B'表示箱子, 'E'表示目的地, 输入保证字符'P', 'B', 'E'各只有一个。
若无法完成任务, 则输出-1, 否则输出的第一行有一个数字n, 表示将箱子移至目的地的最少步数, 第二行有n个字符, 表示玩家的移动步骤, 其中'L'表示左移, 'R'表示右移, 'U'表示上移, 'D'表示下移。(若存在多种满足题意的方案, 则任意一组答案都可以通过本题)
6 7
...*...
.*.*.*.
.*...*.
.*.**..
.****B*
.....EP
26
LLLLLLUUUUURRDDRRUURRDDDLD
这是一道SPECIAL JUDGE的题目, 每组数据, 时限1s
doraemon @ xmu
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
#define N 35
int n,m,op[4][2]={1,0,0,1,-1,0,0,-1};
char mat[N][N],path[1000000],mp[3][3];
struct node
{
int x,y;
}p,e,b;
int vis[N][N][N][N],dp[N][N][N][N];
struct point
{
int x1,y1,x2,y2;
point(){}
point(int a,int b,int c,int d):x1(a),y1(b),x2(c),y2(d){}
}pa[N][N][N][N];
int bfs()
{
int i,ans,x,y,tag;
node temp,u,B,temB;
memset(vis,0,sizeof(vis));
memset(dp,63,sizeof(dp));
vis[p.x][p.y][b.x][b.y]=1;
tag=dp[p.x][p.y][b.x][b.y];
dp[p.x][p.y][b.x][b.y]=0;
queue <node > que,box;
que.push(p);box.push(b);
while(!que.empty())
{
u=que.front();que.pop();
B=box.front();box.pop();
for(i=0;i<4;i++)
{
temp=u;temB=B;
temp.x+=op[i][0];
temp.y+=op[i][1];
if(temp.x<1||temp.x>n||temp.y<1||temp.y>m||mat[temp.x][temp.y]=='*') continue;
if(temp.x==B.x&&temp.y==B.y)
{
temB.x+=op[i][0];
temB.y+=op[i][1];
if(temB.x<1||temB.x>n||temB.y<1||temB.y>m||mat[temB.x][temB.y]=='*') continue;
}
if(dp[u.x][u.y][B.x][B.y]+1<dp[temp.x][temp.y][temB.x][temB.y])
{
pa[temp.x][temp.y][temB.x][temB.y]=point(u.x,u.y,B.x,B.y);
dp[temp.x][temp.y][temB.x][temB.y]=dp[u.x][u.y][B.x][B.y]+1;
if(!vis[temp.x][temp.y][temB.x][temB.y])
{
vis[temp.x][temp.y][temB.x][temB.y]=1;
que.push(temp);box.push(temB);
}
if(temB.x==e.x&&temB.y==e.y) break;
}
}
if(temB.x==e.x&&temB.y==e.y) break;
vis[u.x][u.y][B.x][B.y]=0;
}
point end;
ans=tag;
for(i=0;i<4;i++)
{
temp=e;
temp.x+=op[i][0];
temp.y+=op[i][1];
if(temp.x<1||temp.x>n||temp.y<1||temp.y>m||mat[temp.x][temp.y]=='*') continue;
if(dp[temp.x][temp.y][e.x][e.y]<ans)
{
ans=dp[temp.x][temp.y][e.x][e.y];
end=point(temp.x,temp.y,e.x,e.y);
}
}
if(ans==tag)
return -1;
i=0;
while(end.x1!=p.x||end.y1!=p.y||end.x2!=b.x||end.y2!=b.y){
x=end.x1-pa[end.x1][end.y1][end.x2][end.y2].x1;
y=end.y1-pa[end.x1][end.y1][end.x2][end.y2].y1;
path[i++]=mp[x+1][y+1];
end=pa[end.x1][end.y1][end.x2][end.y2];
}
x=i;
path[i]=0;
for(i=0;i<x/2;i++) swap(path[i],path[x-i-1]);
return ans;
}
int main()
{
int i,j,ans;
mp[2][1]='D';mp[1][2]='R';
mp[0][1]='U';mp[1][0]='L';
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%s",mat[i]+1);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(mat[i][j]=='P')
{
p.x=i;p.y=j;
}
if(mat[i][j]=='E')
{
e.x=i;e.y=j;
}
if(mat[i][j]=='B')
{
b.x=i;b.y=j;
}
}
}
ans=bfs();
if(ans!=-1) printf("%d\n%s\n",ans,path);
else printf("-1\n");
}
return 0;
}
/*
5 4
*...
*...
*...
.*BE
.P..
*/