E - Stronger Takahashi (0-1BFS)

题目链接
在这里插入图片描述在这里插入图片描述

Sample Input 1
5 5
…#…
#.#.#
##.##
#.#.#
…#…
Sample Output 1
1

Sample Input 2
5 7
. . . . . . .
######.
. . . . . . .
.######

Sample Output 2
0

Sample Input 3
8 8
.#######
########
########
########
########
########
########
#######.
Sample Output 3
5

题解
假设他在需要时才出拳,我们可以假设 2 × 2 的破坏方块区域与高桥所在的方格相邻。当高桥在标记的地方上时 (下图中的 T),在单次出拳后,他可以移动到任何标有 * 的方格,而不管这些方格的先前状态如何。
在这里插入图片描述
因此,我们可以假设步行到相邻地方的成本为 0 ,并且移动到任何 * 方格后一拳成本为1,执行01-BFS来解决问题。计算复杂度O(HW)。

双端队列BFS代码

#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define ll long long int
#define endl '\n'
typedef pair<int, int> PII;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
const int N = 1e4 + 7;
 
int n, m;
char a[N][N];
int dis[N][N];
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};
 
void bfs(int sx, int sy) {
    mem(dis, inf);
    deque<PII> q;
    dis[sx][sy] = 0;
    q.push_front({sx, sy});
    while (!q.empty()) {
        auto t = q.front();
        q.pop_front();
        int x = t.first, y = t.second;
        for (int i = 0; i < 4; i++) {
            int xx = dx[i] + x;
            int yy = dy[i] + y;
            if (xx < 1 || xx > n || yy < 1 || yy > m)
                continue;
            if (a[xx][yy] == '.') {
                if (dis[x][y] < dis[xx][yy]) {
                    dis[xx][yy] = dis[x][y];
                    q.push_front({xx, yy});
                }
            } else {
                for (int i = -1; i <= 1; i++) {
                    for (int j = -1; j <= 1; j++) {
                        int xxx = i + xx;
                        int yyy = j + yy;
                        if (xxx < 1 || xxx > n || yyy < 1 || yyy > m)
                            continue;
                        if (dis[x][y] + 1 < dis[xxx][yyy]) {
                            dis[xxx][yyy] = dis[x][y] + 1;
                            q.push_back({xxx, yyy});
                        }
                    }
                }
            }
        }
    }
}
signed main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i] + 1;
    bfs(1, 1);
    cout << dis[n][m] << endl;
    return 0;
}

优先队列BFS代码 类似于Dijkstra

#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define ll long long int
#define endl '\n'
typedef pair<int, int> PII;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
const int N = 1e4 + 7;
 
int n, m;
typedef pair<int, PII> PIII;
char a[N][N];
int dis[N][N];
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};
void bfs(int sx, int sy) {
    mem(dis, inf);
    priority_queue<PIII, vector<PIII>, greater<PIII>> q;
    dis[sx][sy] = 0;
    q.push({dis[sx][sy], {sx, sy}});
    while (!q.empty()) {
        auto t = q.top();
        q.pop();
        int dist = t.first;
        int x = t.second.first, y = t.second.second;
        for (int i = 0; i < 4; i++) {
            int xx = dx[i] + x;
            int yy = dy[i] + y;
            if (xx < 1 || xx > n || yy < 1 || yy > m)
                continue;
            if (a[xx][yy] == '.') {
                if (dist < dis[xx][yy]) {
                    dis[xx][yy] = dist;
                    q.push({dis[xx][yy], {xx, yy}});
                }
            } else {
                for (int i = -1; i <= 1; i++) {
                    for (int j = -1; j <= 1; j++) {
                        int xxx = i + xx;
                        int yyy = j + yy;
                        if (xxx < 1 || xxx > n || yyy < 1 || yyy > m)
                            continue;
                        if (dist + 1 < dis[xxx][yyy]) {
                            dis[xxx][yyy] = dist + 1;
                            q.push({dis[xxx][yyy], {xxx, yyy}});
                        }
                    }
                }
            }
        }
    }
}
signed main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i] + 1;
    bfs(1, 1);
    cout << dis[n][m] << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值