思路来自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;
}