两遍BFS:第一次BFS的时候要把每个'S'点右边的'B'点变为'S'点,第二次直接BFS即可,为减少代码量,第二次的直接BFS也可不重新写而用第一次的
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MOVE[3][2] = {
{0, 1},//right
{1, 0},//down
{0, -1}//left
};
/********************** problem **********************/
int M, N;
char map[200][201];
bool vis[200][200];
bool inputMap()
{
scanf("%d%d", &M, &N);
if(M == 0) return false;
while(getchar() != '\n');
for(int i = 0; i < M; ++i) gets(map[i]);
return true;
}
void outputMap()
{
for(int i = 0; i < M; ++i) puts(map[i]);
}
bool isOutOfBounds(int r, int c)
{
return r < 0 || r >= M || c < 0 || c >= N;
}
struct Point{
int r, c;
Point(int rr, int cc):r(rr), c(cc){}
};
int bfs()
{
queue<Point> q;
//step 0: initialize
for(int i = 0; i < M; ++i) memset(vis[i], false, N);
//step 1: find start at up, right to left
for(int c = N - 2; c > 0; --c){
if(map[0][c] == 'S'){
q.push(Point(0, c));
vis[0][c] = true;
}
}
//step 2: bfs to find way to bottom
int level = 1;
while(!q.empty()){
for(int n = q.size(); n > 0; --n){
Point now = q.front();
q.pop();
for(int i = 0; i < 3; ++i){
int r = now.r + MOVE[i][0], c = now.c + MOVE[i][1];
if(isOutOfBounds(r, c) || map[r][c] != 'S' || vis[r][c]) continue;
q.push(Point(r, c));
vis[r][c] = true;
}
if(!isOutOfBounds(now.r, now.c+1) && map[now.r][now.c+1] == 'B')
map[now.r][now.c+1] = 'S';
if(now.r + 1 == M) return level;
}
++level;
}
return -1;
}
/********************** test **********************/
int main()
{
while(inputMap()){
bfs();
printf("%d\n", bfs());
}
return 0;
}