hdoj 1732(推箱子)(利用hash来判断状态,而不是map)
来源:互联网 发布:医生移动工作站软件 编辑:程序博客网 时间:2024/04/29 18:26
#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;}//把第一个点的脚步做成0now.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;}}}