POJ 2312 bfs

原文链接: POJ 2312 bfs

上一篇: POJ 1011/HDU 1455 dfs 剪枝

下一篇: HDU 1242 bfs

普通队列:
挺有趣的一道题目,然而很容易WA,我就WA了一次,虽然我Debug的时候已经知道哪里出问题了,就是比如说我搜到B和E时,从B搜第三个点,B左边的E就被搜了,step为3,然而其实他是step为2,
这里的处理方法很是巧妙,可以从B出发时,把B换成E,step+1,形成一个新的结点加入到队列中去.
之后,和杰哥交流了这下题,我对这个BFS又有了新的一点认识,BFS时,每次搜索的点,都要是同一级别的点,想这里B,和E就不是同一级别的点,所以将这个B,分成两部,注意B搜完后不要标记,B还没有访问完。
从这道题,我也对bfs有了更深的理解,“bfs之所以能最快找到最优解,就是因为它每次操作一步(这里的操作一步,很灵活,例如题目中的破坏砖墙),而while()里面的语句就是一次操作了!”

这道题中B点需要操作两步,所以遇到B点后不能+2后直接压进队列,需要在原地停一下,不能扩展到其他点,相当于他只能扩展到自身,所以就把自身压进队列里map[x][y]='E'是因为破坏砖墙一次就够了,不然下次,还是'B',不断压进队列,不断在原地停留

平常一般是考虑“入队列” 的点,这次要考虑“出队列” 的点是否满足条件!

普通队列

16ms

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>

#define LL long long
int const MAX = 1e6 + 1;
int const INF = 1 << 30;
double const EPS = 0.00000001;
using namespace std;

char g[303][303];
bool vis[303][303];
int n, m, ans;

struct Node {
    int x, y, step;
    Node(int x = 0, int y = 0, int step = 0) : x(x), y(y), step(step){}
};


Node st, ed;

void setVis(Node nd){
    vis[nd.x][nd.y] = 1;
}

int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int main(){
    while (scanf("%d%d", &n, &m), n){
        for (int i = 0; i < n; i++){
            scanf("%s", g[i]);
            for (int j = 0; j < m; j++){
                if (g[i][j] == 'Y')
                    st.x = i, st.y = j, st.step = 0;
                if (g[i][j] == 'T')
                    ed.x = i, ed.y = j;
            }
        }

        memset(vis, 0, sizeof(vis));
        queue<Node> q;
        q.push(st);
        setVis(st);
        ans = -1;
        while (!q.empty()){
            Node nd = q.front();
            q.pop();
            if (nd.x == ed.x && nd.y == ed.y){
                ans = nd.step;
                break;
            }
            if (g[nd.x][nd.y] == 'B'){
                q.push(Node(nd.x, nd.y, nd.step + 1));
                g[nd.x][nd.y] = 'E';
                continue;
            }
            for (int k = 0; k < 4; k++){
                int nx = nd.x + dir[k][0], ny = nd.y + dir[k][1], ns = nd.step + 1;
                if (nx < 0 || ny < 0 || nx >= n || ny >= m ||
                    vis[nx][ny] || g[nx][ny] == 'S' || g[nx][ny] == 'R') continue;
                // if (g[nx][ny] == 'B') ns++;
                Node t(nx, ny, ns);
                q.push(t);
                setVis(t);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

优先队列

注意优先队列和排序的比较函不一样(╯‵□′)╯︵┻━┻

16ms

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>

#define LL long long
int const MAX = 1e6 + 1;
int const INF = 1 << 30;
double const EPS = 0.00000001;
using namespace std;

char g[303][303];
bool vis[303][303];
int n, m, ans;

struct Node {
    int x, y, step;
    Node(int x = 0, int y = 0, int step = 0) : x(x), y(y), step(step){}
};

bool operator < (Node n1, Node n2){
    return n1.step > n2.step;
}

Node st, ed;

void setVis(Node nd){
    vis[nd.x][nd.y] = 1;
}

int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int main(){
    while (scanf("%d%d", &n, &m), n){
        for (int i = 0; i < n; i++){
            scanf("%s", g[i]);
            for (int j = 0; j < m; j++){
                if (g[i][j] == 'Y')
                    st.x = i, st.y = j, st.step = 0;
                if (g[i][j] == 'T')
                    ed.x = i, ed.y = j;
            }
        }

        memset(vis, 0, sizeof(vis));
        priority_queue<Node> q;
        q.push(st);
        setVis(st);
        ans = -1;
        while (!q.empty()){
            Node nd = q.top();
            q.pop();
            if (nd.x == ed.x && nd.y == ed.y){
                ans = nd.step;
                break;
            }
            for (int k = 0; k < 4; k++){
                int nx = nd.x + dir[k][0], ny = nd.y + dir[k][1], ns = nd.step + 1;
                if (nx < 0 || ny < 0 || nx >= n || ny >= m ||
                    vis[nx][ny] || g[nx][ny] == 'S' || g[nx][ny] == 'R') continue;
                if (g[nx][ny] == 'B') ns++;
                Node t(nx, ny, ns);
                q.push(t);
                setVis(t);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值