蒜头君回家(BFS)

在这里插入图片描述
在这里插入图片描述
样例输入

8 10
P.####.#P#
..#..#...#
..#T##.#.#
..........
..##.#####
..........
#####...##
###....S##

样例输出

21

方法1
bfs 的时候标记数组多开一维度表示是否已经取得了钥匙的状态。如果到达终点并且取得钥匙的状态被标记,bfs 结束。

#include<bits/stdc++.h>
using namespace std;
int n,m,sx,sy,ex,ey;
char mp[2005][2005];
bool vis[2005][2005][2];//第三维标记是否有钥匙,0:没有,1:有
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
struct Node{
    int x,y;
    int step;
    bool flag;//当前状态是否拿到钥匙
};
void bfs(int x,int y){
    queue<Node> q;
    q.push({x,y,0,false});
    vis[x][y][0]=true;
    while(!q.empty()){
        Node now=q.front();
        q.pop();
        if(mp[now.x][now.y]=='T'){
            if(now.flag){
                 cout<<now.step<<endl;
                 break;
            }
            continue;
        }
        for(int i=0;i<4;i++){
            int tx=now.x+dir[i][0];
            int ty=now.y+dir[i][1];
            if(!vis[tx][ty][now.flag]&&tx<n&&tx>=0&&ty<m&&ty>=0&&mp[tx][ty]!='#'){
                vis[tx][ty][now.flag]=true;
                if(mp[tx][ty]=='P'){
                    q.push({tx,ty,now.step+1,true});
                }else {
                    q.push({tx,ty,now.step+1,now.flag});
                }
            }
        }
    }
}
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        cin>>mp[i];
    }
    bool f1=false,f2=false;
    for(int i=0;i<n;i++){//找到起点的位置
        for(int j=0;j<m;j++){
            if(mp[i][j]=='S'){
                sx=i;
                sy=j;
                f1=true;
            }
        }
    }
    bfs(sx,sy);
    return 0;
}

方法2
这道题目是一个技巧题目,我们可以用同一个bfs搜索两次。第一次从当前位置S开始搜索到达所有点的最短路径,第二次从家T开始搜索到达所有点的最短路径。最后我们计算每一个P,计算出S到P加上T到P之和,这个代表找这把钥匙回家的最短路径。然后我们找出他们中最小的就可以了。

#include <cstdio>
2
#include <queue>
3
#include <cstring>
4
#include <algorithm>
5
using namespace std;
67
const int MAXN = 2010;
8
const int INF = 0x3f3f3f3f;
910
int n, m;
11
int vis[MAXN][MAXN];
12
int ret[2][MAXN][MAXN];
13
char a[MAXN][MAXN];
14
int xx[4] = {1,-1,0,0};
15
int yy[4] = {0,0,1,-1};
1617
void bfs(int xxx, int yyy, int d) {
18
    queue< pair<int, int> > q;
19
    q.push(make_pair(xxx, yyy));
20
    vis[xxx][yyy] = 1;
21
    ret[d][xxx][yyy] = 0;
22
    while(!q.empty()) {
23
        int tx = q.front().first;
24
        int ty = q.front().second;
25
        q.pop();
26
        for (int i = 0;i < 4; ++i) {
27
            int x = tx + xx[i];
28
            int y = ty + yy[i];
29
            if (x >= 0 && x < n && y >= 0 && y < m && a[x][y] != '#' && !vis[x][y]) {
30
                ret[d][x][y] = ret[d][tx][ty] + 1;
31
                vis[x][y] = 1;
32
                q.push(make_pair(x, y));
33
            }
34
        }
35
    }
36
}
3738
int main() {
39
    freopen("home.in", "r", stdin);
40
    freopen("home.out", "w", stdout);
41
    queue< pair<int, int> > q;
42
    scanf("%d %d", &n, &m);
43
    memset(ret, INF, sizeof(ret));
44
    memset(vis, 0, sizeof(vis));
45
    int sx, sy;
46
    int tx, ty;
47
    for (int i = 0;i < n; ++i) {
48
        scanf("%s", a[i]);
49
        for (int j = 0;j < m; ++j) {
50
            if (a[i][j] == 'P') {
51
                q.push(make_pair(i, j));
52
            } else if (a[i][j] == 'S') {
53
                sx = i;
54
                sy = j;
55
            } else if (a[i][j] == 'T') {
56
                tx = i;
57
                ty = j;
58
            }
59
        }
60
    }
61
    bfs(sx, sy, 0);
62
    memset(vis, 0, sizeof(vis));
63
    bfs(tx, ty, 1);
64
    int ans = INF;
65
    while(!q.empty()) {
66
        int x = q.front().first;
67
        int y = q.front().second;
68
        q.pop();
69
        ans = min(ans, ret[0][x][y] + ret[1][x][y]);
70
    }
71
    printf("%d\n", ans);
72
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值