pku 1475 Pushing Boxes
题目地址:http://acm.pku.edu.cn/JudgeOnline/problem?id=1475
题目大意:
模拟推箱子,给你一个矩阵,矩阵中有些是墙,再给你箱子,目标点和人的坐标(二者的初始位置不一定相邻),问是否存在一个路径使得人可以把箱子推到终点,如果存在,输出最短路径,要是最短路径有多条,可以输出任意一条。
具体分析:
这题比较妙,首先我们要用到双BFS,也就是BFS中嵌套BFS,我们首先要在(箱子到终点的BFS)这个过程中,每当箱子进行一个合法的移动,我们就可以根据箱子移动后的末位置来反推出人应该在箱子的哪个方向以及具体坐标,然后进行(人到对应的推箱位置的BFS),当然在此过程中应该记录路径。
以后会详细分析。
AC代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
#define N 22
//
int r, c;
char Map[N][N];
bool vis2[N][N];
bool vis1[N][N];
int dirc[4][2] = { {1,0}, {-1,0}, {0,1}, {0,-1} };
char name_walk[4]={'s','n','e','w'};
char name_push[4]={'S','N','E','W'};
//
struct Node
{
int B_x, B_y;
int P_x, P_y;
int step;
char path[N*N*N];
Node(int x = 0):step(x){}
};
int BFS_to_B(Node& t, int xx ,int yy)
{
queue<Node> q;
Node temp, Front ;
temp = t;
q.push(temp);
memset(vis2, 0 ,sizeof(vis2));
vis2[t.P_x][t.P_y] = 1;
vis2[t.B_x][t.B_y] = 1;
while( !q.empty())
{
Front = q.front();
q.pop();
if( Front.P_x == xx && Front.P_y == yy )
{
t = Front;
return 1;
}
for( int i = 0 ;i < 4 ; i++ )
{
temp = Front;
int x = temp.P_x + dirc[i][0];
int y = temp.P_y + dirc[i][1];
if( x>=1 && x<=r && y>=1 && y<=c && Map[x][y]!='#' && !vis2[x][y] )
{
temp.P_x = x;
temp.P_y = y;
temp.path[ temp.step++ ] = name_walk[i];
q.push(temp);
vis2[x][y] = 1;
}
}
}
return 0;
}
int BFS_to_T( Node& t )
{
queue<Node>q;
Node temp ,Front;
temp = t;
q.push(temp);
memset(vis1, 0 ,sizeof(vis1));
vis1[t.B_x][t.B_y] = 1;
while(!q.empty())
{
Front = q.front();
q.pop();
if( Map[ Front.B_x ][ Front.B_y ] == 'T' )
{
for(int i = 0 ;i < Front.step ;i++)
cout << Front.path[i];
cout << endl << endl;
return 1;
}
for(int i = 0 ;i < 4 ;i++)
{
temp = Front;
/*
printf(" Front.P_x is %d ,Front.P_y is %d ", Front.P_x, Front.P_y);
printf("Front.B_x is %d , Front.B_y is %d\n ", Front.B_x, Front.B_y);
*/
int x = Front.B_x + dirc[i][0];
int y = Front.B_y + dirc[i][1];
int xx = Front.B_x - dirc[i][0];
int yy = Front.B_y - dirc[i][1];
if( x>=1 && x<=r && y>=1 && y<=c && Map[x][y]!='#' && xx>=1 && xx<=r && yy>=1 && yy<=c && Map[xx][yy] != '#' && !vis1[x][y])
{
if( BFS_to_B( temp, xx, yy ))
{
temp.B_x = x;
temp.B_y = y;
//cout << Front.B_x << "and" << Front.B_y << endl;
temp.P_x = Front.B_x;
temp.P_y = Front.B_y;
temp.path[temp.step++] = name_push[i];
q.push(temp);
vis1[x][y] = 1;
/*
printf("temp.P_x is %d ,temp.P_y is %d ", temp.P_x, temp.P_y);
printf("temp.B_x is %d , temp.B_y is %d\n ", temp.B_x, temp.B_y);
cout << "---------------------" << endl;
*/
}
}
}
}
cout << "Impossible." << endl << endl;
return 0;
}
int main()
{
int Maze = 0;
while(cin >> r >> c)
{
Node First;
if(!r && !c)
break;
Maze++;
for(int i = 1 ;i <= r ; i++)
for(int j = 1 ;j <= c ;j++)
{
cin >> Map[i][j];
if( Map[i][j] == 'B' )
First.B_x = i , First.B_y = j;
if( Map[i][j] == 'S' )
First.P_x = i, First.P_y =j;
}
printf("Maze #%d\n",Maze);
BFS_to_T(First);
}
return 0;
}
/*
1 4
SB.T
*/
/*
5 1
.
B
S
.
T
*/