ABC213E - Stronger Takahashi

問題

https://atcoder.jp/contests/abc213/tasks/abc213_e

略説

パンチを行うのは必要になったタイミングでよい

あるマスから上下左右の移動可能なマスに重み0の辺、パンチを行うことで進めるようになるマスに重み1の辺を貼り、最短経路を求める(01BFS)

計算量はO(HW)となる

ACコード
#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define ll long long
using namespace std;

constexpr int INF = 1<<30;
constexpr int dy[] = {-1,0,1,0};
constexpr int dx[] = {0,1,0,-1};

int H, W;
string S[550];
int dis[550][550];

void solve() {
    cin >> H >> W;
    for (int i=0; i<H; i++) cin >> S[i];
    deque<pair<int,int>> deq;
    deq.push_back(make_pair(0,0));
    for (int i=0; i<H; i++) fill(dis[i], dis[i]+W, INF);
    dis[0][0] = 0;
    while (!deq.empty()) {
        auto [y, x] = deq.front();
        deq.pop_front();
        for (int i=0; i<4; i++) {
            int y2 = y+dy[i], x2 = x+dx[i];
            if (y2<0 || H<=y2 || x2<0 || W<=x2) continue;
            if (S[y2][x2] == '#') continue;
            if (dis[y2][x2] <= dis[y][x]) continue;
            dis[y2][x2] = dis[y][x];
            deq.push_front(make_pair(y2, x2));
        }
        for (int i=-2; i<=2; i++) for (int j=-2; j<=2; j++) {
            if (i==0 && j==0) continue;
            if (abs(i)==2 && abs(j)==2) continue;
            int y2 = y+i, x2 = x+j;
            if (y2<0 || H<=y2 || x2<0 || W<=x2) continue;
            if (dis[y2][x2] <= dis[y][x]+1) continue;
            dis[y2][x2] = dis[y][x]+1;
            deq.push_back(make_pair(y2, x2));
        }
    }
    cout << dis[H-1][W-1] << '\n';
}

signed main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    solve();
    return 0;
}