#include <iostream>
#include <queue>
#include <stdio.h>
using namespace std;
char map[10][10];//地图
int n,m,lmin;
int x[5] = {1,-1,0,0};//方向
int y[5] = {0,0,1,-1};//方向
bool hash[8][8][8][8][8][8][8][8];//这个是人的状态
class Point
{
public:
int x,y;
};
class State
{
public:
Point hum,box[3];
int step;
public:
bool isok()
{
if(hum.x >= 0 && hum.x < n && hum.y >= 0 && hum.y < m && map[hum.x][hum.y] != '#')
return true;
return false;
}
};
State now,next;
queue<State>q;
void setHash(State node)
{
hash[node.hum.x][node.hum.y][node.box[0].x][node.box[0].y][node.box[1].x][node.box[1].y][node.box[2].x][node.box[2].y] = true;
}
bool getHash(State node)
{
return hash[node.hum.x][node.hum.y][node.box[0].x][node.box[0].y][node.box[1].x][node.box[1].y][node.box[2].x][node.box[2].y];
}
//判断这个地方是哪个箱子
int isBox(State next)
{
for(int i=0;i<3;i++)
{
if(next.hum.x==next.box[i].x && next.hum.y==next.box[i].y)
{
return i;
}
}
return -1;
}
//人(第which个箱子)能否移动(which是箱子的id箱子的移动方向跟人的移动方向相同)
bool canMove(State next,int dir,int which)
{
//移动人
next.hum.x+=x[dir];
next.hum.y+=y[dir];
//是否越界(如果说一移动,越界啦,那么返回false)
if(!next.isok())
return false;
//如果说一移动,下面是箱子,那么返回false(如果说是第which个箱子,跳过)
int i;
for(i=0;i<3;i++)
{
if(i!=which && (next.hum.x == next.box[i].x && next.hum.y == next.box[i].y))
{
return false;
}
}
return true;
}
//是否结束(三个箱子都在@的地方)
bool finish(State next)
{
if(map[next.box[0].x][next.box[0].y] == '@' && map[next.box[1].x][next.box[1].y] == '@' && map[next.box[2].x][next.box[2].y] == '@')
return true;
return false;
}
void bfs()
{
int i;
//如果队列不为空
while(!q.empty())
{
//出栈一个
now=q.front();
q.pop();
//是否结束
if(finish(now))
{
if(lmin>now.step)
{
lmin=now.step;
}
break;//也就是说继续运算,但是不再向下
}
//四个方向
for(i=0;i<4;i++)
{
//向下走一步
next=now;
next.hum.x+=x[i];
next.hum.y+=y[i];
next.step++;//步子++
//这个是否越界
if(next.isok())
{
int which=isBox(next);
//如果说下一步是箱子(首先要判断是否移动箱子,那么再向下走一步,判断能否走)
if(which != -1)
{
if(canMove(next,i,which))
{
//移动一步箱子
next.box[which].x+=x[i];
next.box[which].y+=y[i];
//是否访问过(如果访问过,跳过,如果没有访问过,压入队列)
if(!getHash(next))
{
//标记访问过(压入队列)
setHash(next);
q.push(next);
}
}
}
//如果说下一个不是箱子
else
{
//如果说这个点没有访问过
if(!getHash(next))
{
//设置访问过
setHash(next);
//压入队列
q.push(next);
}
}
}
}
}
}
int main()
{
int i,j;
while(scanf("%d %d",&n,&m)!=EOF)
{
//输入
for(i=0;i<n;i++)
scanf("%s",map[i]);
//初始化
int cnt=0;
for(i = 0; i < n; i++)
for(j = 0;j < m; j++)
{
if(map[i][j]=='X')
now.hum.x=i,now.hum.y=j;
if(map[i][j]=='*')
now.box[cnt].x=i,now.box[cnt++].y=j;
}
//把第一个点的脚步做成0
now.step=0;
memset(hash,false,sizeof(hash));
//吧第一个点表示为访问过
setHash(now);
//初始化
lmin=100000;
//清空队列
while(!q.empty())
q.pop();
//把第一个点压入队列当中
q.push(now);
//处理
bfs();
//输出
if(lmin==100000)
{
cout<<"-1"<<endl;
}
else
{
cout<<lmin<<endl;
}
}
}
hdoj 1732(推箱子)(利用hash来判断状态,而不是map)
最新推荐文章于 2016-08-23 17:25:00 发布
