POJ-2056(BFS)

两遍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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值