1326.推箱子
时限:1000ms 内存限制:10000K 总时限:3000ms
描述
绝大多数人都玩过推箱子的游戏,控制一个人将箱子推动到目标位置即获得胜利。现请你编写一个程序,判断将箱子推到目标位置至少需要多少步。
输入
推箱子的平面区域为固定大小(10*10),使用10行10列输入推箱子的初始局面。其中,0代表空格,1代表墙,2代表箱子,3代表目标位置,4代表人。
注:游戏中只有一个箱子,一个目标位置,一个人。
输出
输出将箱子推到目标位置的最小步数;若箱子不可能被推到目标位置,输出-1。
输入样例
0000000000
0000000300
0100000000
0100000000
0101111100
0000010000
0000010000
0020010040
0000010000
0000010000
输出样例
34
解析:这个也是一个很经典的广搜和队列解决的问题。但这个跟前面的跳马,二阶魔方相比又有一点不同。前面的那些题都是每步有一个状态,这个状态是自身产生的一个状态,通过某种方法记录下来进行比较即可。但这个题中的推箱子,若没有人推,只需要让箱子自行移动,每步一个状态记录查重就可以,即退化成了老鼠闯迷宫,但是这个箱子是有人推的,还要考虑这个人所处的位置不同导致推箱子方式不一样。而且这个求的是人的最小步数而不是箱子走的步数。
举例子来说,现在这个人推箱子向下走了一步,那么完成之后这个人就位于箱子的上方。下一步要想把箱子向右推,这个人还得花额外的两步走到箱子的左边,还得考虑箱子左边是不是有位置才能过去推。这里就涉及到人走的问题。
好我又回来了!
我get到了解决方法。既然是求人走的步数,那么我们就以人走为基准,人可以向四个方向移动,当移动完后发现自己站在箱子的位置上,那么箱子也向刚刚的移动的方向移动一格即可。当然这里的used和step数组是四维的,分别是人的位置坐标和箱子的位置坐标。详见代码:
#include <iostream>
#include<queue>
#include<string.h>
#include<stdio.h>
using namespace std;
int m[10][10];
struct node{
int box[2];
int ren[2];
int useful;
};
int dirx[4]={0,0,1,-1};
int diry[4]={1,-1,0,0};
int used[10][10][10][10];
int step[10][10][10][10];
int sx,sy;//箱子起始位置
int tx,ty;//箱子终点位置
int ex,ey;
queue<node> q;
void init_readdata()
{
while(!q.empty())
q.pop();
memset(m,0,sizeof(m));
memset(used,0,sizeof(used));
memset(step,0,sizeof(step));
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
char ch;
cin>>ch;
m[i][j]=int(ch)-48;
if(m[i][j]==3)
{
tx=i;
ty=j;
}
else if(m[i][j]==2)
{
sx=i;
sy=j;
}
else if(m[i][j]==4)
{
ex=i;
ey=j;
}
}
getchar();
}
node start;
start.box[0]=sx;
start.box[1]=sy;
start.ren[0]=ex;
start.ren[1]=ey;
q.push(start);
used[sx][sy][ex][ey]=1;
step[sx][sy][ex][ey]=1;
}
node moveto(node cur,int i)
{
node n=cur;
n.ren[0]=cur.ren[0]+dirx[i];
n.ren[1]=cur.ren[1]+dirx[i];
n.useful=0;
if(n.ren[0]==cur.box[0]&&n.ren[1]==cur.box[1])
{
n.box[0]=cur.box[0]+dirx[i];
n.box[1]=cur.box[1]+dirx[i];
}
if(n.ren[0]>=0&&n.ren[0]<10&&n.ren[1]>=0&&n.ren[1]<10)
{
if(n.box[0]>=0&&n.box[0]<10&&n.box[1]>=0&&n.box[1]<10)
{
if(m[n.ren[0]][n.ren[1]]!=1&&m[n.box[0]][n.box[1]]!=1)
n.useful=1;
}
}
return n;
}
int bfs()
{
while(!q.empty())
{
node cur=q.front();
q.pop();
if(cur.box[0]==tx&&cur.box[1]==ty)
return step[cur.box[0]][cur.box[1]][cur.ren[0]][cur.ren[1]];
else
{
for(int i=0;i<4;i++)
{
node res=moveto(cur,i);
if(res.useful)
{
if(!used[res.box[0]][res.box[1]][res.ren[0]][res.ren[1]])
{
q.push(res);
used[res.box[0]][res.box[1]][res.ren[0]][res.ren[1]]=1;
step[res.box[0]][res.box[1]][res.ren[0]][res.ren[1]]=1+step[cur.box[0]][cur.box[1]][cur.ren[0]][cur.ren[1]];
}
}
}
}
}
return 0;
}
int main()
{
init_readdata();
cout<<bfs()<<endl;
return 0;
}