思路来自DISCUSS,嵌套的BFS,外重BFS是箱子的,内重BFS是人的(即判断人否能到达外重BFS求出来的能把箱子推到该位置的位置)
然后就是路径的记录,我开了一个大字符串数组来记录人走的路径(可以通过内重BFS记录),外重BFS则记录推箱子的路径,反正有点繁琐,
要比较细心。
代码
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int dx[]={-1,1,0,0};
int dy[]={0,0,1,-1};
//N, S, E, W
int r,c;
char map[25][25];
int T = 0;
struct point
{
int x, y;
point()
{}
point(int xx,int yy):x(xx),y(yy)
{}
};
struct state
{
point box;
point face;
int pre;
int top;
state()
{}
state(point boxx,point facee,int pree,int topp):box(boxx),face(facee),pre(pree),top(topp)
{}
};
struct faces
{
int x,y;
int pre;
faces()
{}
faces(int xx,int yy,int pree):x(xx),y(yy),pre(pree)
{
}
};
point pTarget;
point pFace;
point pBox;
state q1[405*405];
faces q2[405*405*5];
int mark[22][22][22][22];
int fmark[22][22];
char path[6000][400];
int pathCnt;
inline bool isOk(int x,int y)
{
if (x>=0&&x<r&&y>=0&&y<c&&map[x][y]!='#')
{
return true;
}
return false;
}
inline bool isOk1(int x,int y,int curBx,int curBy)
{
if (x>=0&&x<r&&y>=0&&y<c&&map[x][y]!='#'&&!(x==curBx&&y==curBy))
{
return true;
}
return false;
}
char str[400];
bool bfs2(int curx,int cury, int tx,int ty,int &top,point boxp)
{
if(curx==tx&&cury==ty)
{
top=-1;
return true;
}
bool flag = false;
memset(fmark,0,sizeof(fmark));
int front = -1;
int rear = -1;
int pre=-1;
q2[++rear] = faces(curx,cury,-1);
while (front<rear)
{
faces cur = q2[++front];
int cx = cur.x;
int cy = cur.y;
pre = front;
if (fmark[cx][cy])
{
continue;
}
fmark[cx][cy] = 1;
if (cx==tx&&cy==ty)
{
flag = true;
break;
}
for (int i=0;i<4;i++)
{
int tx = cx + dx[i];
int ty = cy + dy[i];
if (isOk1(tx,ty,boxp.x,boxp.y))
{
q2[++rear] = faces(tx,ty,pre);
}
}
}
if (!flag)
{
return false;
}
else
{
if (pre==-1)
{
top = pre;
}
else
{
int ttpre = q2[pre].pre;
int i = 0;
while (ttpre!=-1)
{
int tx = q2[pre].x - q2[ttpre].x;
int ty = q2[pre].y -q2[ttpre].y;
if (tx==-1&&ty==0)
{
str[i++] ='n';
}
else if (tx==1&&ty==0)
{
str[i++] ='s';
}
else if (tx==0&&ty==1)
{
str[i++] ='e';
}
else if (tx==0&&ty==-1)
{
str[i++] ='w';
}
pre = ttpre;
ttpre = q2[pre].pre;
}
for(int j=0;j<i;j++)
{
path[pathCnt][j] = str[i-j-1];
}
path[pathCnt][i] = '\0';
top = pathCnt++;
}
return true;
}
}
void output(int pre)
{
if (q1[pre].pre==-1)
{
return;
}
else
{
state s = q1[pre];
output(s.pre);
if(s.top!=-1)
{
printf("%s",path[s.top]);
}
int tx = s.box.x - s.face.x;
int ty = s.box.y - s.face.y;
if (tx==-1&&ty==0)
{
putchar('N');
}
else if (tx==1&&ty==0)
{
putchar('S');
}
else if (tx==0&&ty==1)
{
putchar('E');
}
else if (tx==0&&ty==-1)
{
putchar('W');
}
}
}
void bfs1()
{
bool flag = false;
memset(mark,0,sizeof(mark));
int front = -1;
int rear = -1;
int pre;
q1[++rear] = state(pBox,pFace,-1,-1);
while (front<rear)
{
state cur = q1[++front];
int curBx = cur.box.x;
int curBy = cur.box.y;
int curFx = cur.face.x;
int curFy = cur.face.y;
pre = front;
if (mark[curBx][curBy][curFx][curFy])
{
continue;
}
if (curBx==pTarget.x&&curBy==pTarget.y)
{
flag = true;
break;
}
mark[curBx][curBy][curFx][curFy] = 1;
for (int i=0;i<4;i++)
{
int nextBx = curBx + dx[i];
int nextBy = curBy + dy[i];
if (isOk(nextBx,nextBy))
{
int tx = curBx +dx[i]*(-1);
int ty = curBy +dy[i]*(-1);
int ttop=-1;
if (isOk(tx,ty)&&bfs2(curFx,curFy,tx,ty,ttop,cur.box))
{
q1[++rear] = state(point(nextBx,nextBy),
point(curBx,curBy),pre,ttop);
}
}
}
}
printf("Maze #%d\n",T);
if (!flag)
{
printf("Impossible.\n");
}
else
{
output(pre);
printf("\n");
}
}
int main()
{
while (scanf("%d%d",&r,&c)!=EOF&&!(r==0&&c==0))
{
pathCnt = 0;
T++;
for (int i=0;i<r;i++)
{
scanf("%s",map[i]);
for (int j=0;j<c;j++)
{
if (map[i][j]=='S')
{
pFace = point(i,j);
}
else if (map[i][j]=='B')
{
pBox = point(i,j);
}
else if (map[i][j]=='T')
{
pTarget = point(i,j);
}
}
}
bfs1();
printf("\n");
}
return 0;
}
#include <cstring>
#include <cstdio>
using namespace std;
int dx[]={-1,1,0,0};
int dy[]={0,0,1,-1};
//N, S, E, W
int r,c;
char map[25][25];
int T = 0;
struct point
{
int x, y;
point()
{}
point(int xx,int yy):x(xx),y(yy)
{}
};
struct state
{
point box;
point face;
int pre;
int top;
state()
{}
state(point boxx,point facee,int pree,int topp):box(boxx),face(facee),pre(pree),top(topp)
{}
};
struct faces
{
int x,y;
int pre;
faces()
{}
faces(int xx,int yy,int pree):x(xx),y(yy),pre(pree)
{
}
};
point pTarget;
point pFace;
point pBox;
state q1[405*405];
faces q2[405*405*5];
int mark[22][22][22][22];
int fmark[22][22];
char path[6000][400];
int pathCnt;
inline bool isOk(int x,int y)
{
if (x>=0&&x<r&&y>=0&&y<c&&map[x][y]!='#')
{
return true;
}
return false;
}
inline bool isOk1(int x,int y,int curBx,int curBy)
{
if (x>=0&&x<r&&y>=0&&y<c&&map[x][y]!='#'&&!(x==curBx&&y==curBy))
{
return true;
}
return false;
}
char str[400];
bool bfs2(int curx,int cury, int tx,int ty,int &top,point boxp)
{
if(curx==tx&&cury==ty)
{
top=-1;
return true;
}
bool flag = false;
memset(fmark,0,sizeof(fmark));
int front = -1;
int rear = -1;
int pre=-1;
q2[++rear] = faces(curx,cury,-1);
while (front<rear)
{
faces cur = q2[++front];
int cx = cur.x;
int cy = cur.y;
pre = front;
if (fmark[cx][cy])
{
continue;
}
fmark[cx][cy] = 1;
if (cx==tx&&cy==ty)
{
flag = true;
break;
}
for (int i=0;i<4;i++)
{
int tx = cx + dx[i];
int ty = cy + dy[i];
if (isOk1(tx,ty,boxp.x,boxp.y))
{
q2[++rear] = faces(tx,ty,pre);
}
}
}
if (!flag)
{
return false;
}
else
{
if (pre==-1)
{
top = pre;
}
else
{
int ttpre = q2[pre].pre;
int i = 0;
while (ttpre!=-1)
{
int tx = q2[pre].x - q2[ttpre].x;
int ty = q2[pre].y -q2[ttpre].y;
if (tx==-1&&ty==0)
{
str[i++] ='n';
}
else if (tx==1&&ty==0)
{
str[i++] ='s';
}
else if (tx==0&&ty==1)
{
str[i++] ='e';
}
else if (tx==0&&ty==-1)
{
str[i++] ='w';
}
pre = ttpre;
ttpre = q2[pre].pre;
}
for(int j=0;j<i;j++)
{
path[pathCnt][j] = str[i-j-1];
}
path[pathCnt][i] = '\0';
top = pathCnt++;
}
return true;
}
}
void output(int pre)
{
if (q1[pre].pre==-1)
{
return;
}
else
{
state s = q1[pre];
output(s.pre);
if(s.top!=-1)
{
printf("%s",path[s.top]);
}
int tx = s.box.x - s.face.x;
int ty = s.box.y - s.face.y;
if (tx==-1&&ty==0)
{
putchar('N');
}
else if (tx==1&&ty==0)
{
putchar('S');
}
else if (tx==0&&ty==1)
{
putchar('E');
}
else if (tx==0&&ty==-1)
{
putchar('W');
}
}
}
void bfs1()
{
bool flag = false;
memset(mark,0,sizeof(mark));
int front = -1;
int rear = -1;
int pre;
q1[++rear] = state(pBox,pFace,-1,-1);
while (front<rear)
{
state cur = q1[++front];
int curBx = cur.box.x;
int curBy = cur.box.y;
int curFx = cur.face.x;
int curFy = cur.face.y;
pre = front;
if (mark[curBx][curBy][curFx][curFy])
{
continue;
}
if (curBx==pTarget.x&&curBy==pTarget.y)
{
flag = true;
break;
}
mark[curBx][curBy][curFx][curFy] = 1;
for (int i=0;i<4;i++)
{
int nextBx = curBx + dx[i];
int nextBy = curBy + dy[i];
if (isOk(nextBx,nextBy))
{
int tx = curBx +dx[i]*(-1);
int ty = curBy +dy[i]*(-1);
int ttop=-1;
if (isOk(tx,ty)&&bfs2(curFx,curFy,tx,ty,ttop,cur.box))
{
q1[++rear] = state(point(nextBx,nextBy),
point(curBx,curBy),pre,ttop);
}
}
}
}
printf("Maze #%d\n",T);
if (!flag)
{
printf("Impossible.\n");
}
else
{
output(pre);
printf("\n");
}
}
int main()
{
while (scanf("%d%d",&r,&c)!=EOF&&!(r==0&&c==0))
{
pathCnt = 0;
T++;
for (int i=0;i<r;i++)
{
scanf("%s",map[i]);
for (int j=0;j<c;j++)
{
if (map[i][j]=='S')
{
pFace = point(i,j);
}
else if (map[i][j]=='B')
{
pBox = point(i,j);
}
else if (map[i][j]=='T')
{
pTarget = point(i,j);
}
}
}
bfs1();
printf("\n");
}
return 0;
}