点击打开链接地址。
这个题的痛点在于思路问题,而且如何标记已经走过的路线,这里的标记是标记人与三个箱子之间的相对位置,并不是说,你走过了以后,就不能再走了,只要其中一个箱子的位置发生了变化,那么就可以继续走。
代码是模的。也拓宽一下自己的思路。BFS用的还不是得心应手
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
bool Hash[8][8][8][8][8][8][8][8];
char map[8][8];
int n,m,ans;
int dir[4][2]={{0,1,},{0,-1},{1,0},{-1,0}};
struct node
{
int x,y;
};
struct state
{
node h,box[3];
int st;
bool isok()
{
if(h.x>=0&&h.x<n&&h.y>=0&&h.y<m&&map[h.x][h.y]!='#') return true;
return false;
}
}a,b;
void sethash(state cur)//记录状态
{
Hash[cur.h.x][cur.h.y][cur.box[0].x][cur.box[0].y][cur.box[1].x][cur.box[1].y][cur.box[2].x][cur.box[2].y]=true;
}
bool gethash(state cur)//判断当前状态是否走过
{
return Hash[cur.h.x][cur.h.y][cur.box[0].x][cur.box[0].y][cur.box[1].x][cur.box[1].y][cur.box[2].x][cur.box[2].y];
}
bool find(state cur)// 判断箱子是不是都推到洞里去了
{
int i;
for(i=0;i<3;++i){
if(map[cur.box[i].x][cur.box[i].y]!='@') break;
}
if(i!=3) return false;
return true;
}
int isbox(state cur)//判断这个位置是不是箱子,如果是,返回箱子的序号
{
for(int i=0;i<3;++i){
if(cur.h.x==cur.box[i].x&&cur.h.y==cur.box[i].y) return i;
}
return -1;
}
bool logic(state cur,int d,int cnt)//判断同方向上的下一个点,如果位置越界,或者是墙或箱子,返回false;
{
state next;
next.h.x=cur.h.x+dir[d][0];
next.h.y=cur.h.y+dir[d][1];
if(!next.isok()) return false;
for(int i=0;i<3;++i){
if(next.h.x==cur.box[i].x&&next.h.y==cur.box[i].y&&i!=cnt) return false;
}
return true;//可以推箱子
}
int bfs()
{
queue<state> q;
a.st=0;
q.push(a);
while(!q.empty()){
a=q.front(),q.pop();
if(find(a)){
return ans=a.st;
}
for(int i=0;i<4;++i){
b=a;
b.h.x=a.h.x+dir[i][0];
b.h.y=a.h.y+dir[i][1];
b.st=a.st+1;
if(!b.isok()) continue; //位置不合法
int which=isbox(b);
if(which!=-1){//如果 这个位置是箱子
if(logic(b,i,which)){ //同方向上的下个位置是路,把箱子推过去,改变它的坐标
b.box[which].x=b.h.x+dir[i][0];
b.box[which].y=b.h.y+dir[i][1];
if(!gethash(b)){//当前状态没有记录过
sethash(b);//记录状态
q.push(b);//入队
}
}
}
else{//当前位置是路或者是洞,直接走
if(!gethash(b)){
sethash(b);
q.push(b);
}
}
}
}
return -1;
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
while(scanf("%d%d",&n,&m)!=EOF){
getchar();
int cnt=0;
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
map[i][j]=getchar();
if(map[i][j]=='X'){
a.h.x=i,a.h.y=j;
}
if(map[i][j]=='*'){
a.box[cnt].x=i,a.box[cnt++].y=j;//记录每个箱子的坐标
}
}
getchar();
}
memset(Hash,false,sizeof Hash);
sethash(a);
printf("%d\n",bfs());
}
return 0;
}