C++の練習を兼ねて, AtCoder Beginner Contest 020 の 問題C (壁抜け) を解いてみた.
■感想.
1. 問題Cは, 方針が見えなかったので, 解説を参考に, AC版に到達できたと思う.
2. 二分探索, ワーシャル–フロイド法 の 復習が出来たので, 非常に良かったと思う.
3. 引き続き, 時間を見つけて, 過去問の学習を進めていきたいと思う.
本家のサイト AtCoder Beginner Contest 020 解説 の 各リンク を ご覧下さい.
■C++版プログラム(問題C/AC版).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
// 解き直し. // https://www.slideshare.net/chokudai/abc020 // C++(GCC 9.2.1) #include <bits/stdc++.h> using namespace std; using LL = long long; using vs = vector<string>; #define repex(i, a, b, c) for(int i = a; i < b; i += c) #define repx(i, a, b) repex(i, a, b, 1) #define rep(i, n) repx(i, 0, n) #define repr(i, a, b) for(int i = a; i >= b; i--) #define pb push_back int main() { // 1. 入力情報. int H, W, T; scanf("%d %d %d", &H, &W, &T); int sx, sy, gx, gy, A = H * W; vs board; rep(i, H){ char c[22]; scanf("%s", c); string s(c); rep(j, W){ // スタート地点, ゴール地点を設定. if(s[j] == 'S') sx = i, sy = j, s[j] = '.'; if(s[j] == 'G') gx = i, gy = j, s[j] = '.'; } board.pb(s); } // 2. スタート地点, ゴール地点. int s = sx * W + sy; int g = gx * W + gy; // 3. 評価関数. auto f = [&](LL m) -> bool { // 3-1. グラフ作成. LL G[A][A]; rep(i, A) rep(j, A) G[i][j] = 2e10 + 1; rep(i, H){ rep(j, W){ // 出発地点. int cur = i * W + j; // 到達地点(上). if(i) G[cur][cur - W] = (board[i][j] == '#') ? m : 1; // 到達地点(下). if(i < H - 1) G[cur][cur + W] = (board[i][j] == '#') ? m : 1; // 到達地点(左). if(j) G[cur][cur - 1] = (board[i][j] == '#') ? m : 1; // 到達地点(右). if(j < W - 1) G[cur][cur + 1] = (board[i][j] == '#') ? m : 1; } } // 3-2. Warshall–Floyd法(※各頂点間の最短距離を保存). rep(k, A) rep(i, A) rep(j, A) G[i][j] = min(G[i][j], G[i][k] + G[k][j]); // 3-3. 判定結果. return (G[s][g] <= (LL)T); }; // 4. 二分探索で確認してみる. LL l = 0, h = 2e9 + 1; while(l + 1 < h){ LL m = (h + l) >> 1; if(f(m)) l = m; else h = m; // printf("h=%lld l=%lld m=%lld\n", h, l, m); } // 5. 出力. printf("%lld\n", l); return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
[入力例] 2 3 10 S## .#G [出力例] 8 ※AtCoderテストケースより [入力例] 3 4 7 S##G .##. ..#. [出力例] 3 ※AtCoderテストケースより [入力例] 4 4 1000000000 S### #### #### ###G [出力例] 199999999 ※AtCoderテストケースより [入力例] 7 9 30 .#.#.#... S...#.#.# .#.#.#... ....#.#.# .#.#.#... ....#.#.# .#.#.#.G. [出力例] 10 [入力例] 7 8 2022 ###.#### ..#.#..# S.#.#..# ###.#.G# #...#..# #...#..# ###.#### [出力例] 1008 [入力例] 15 19 20220205 .#.#.#.#.#.#.#.#.#. #S#.#.#.#.#.#.#.#.# .#.#.#.#.#.#.#.#.#. ####.####.####.#### #..#.#..#.#..#.#..# ...#.#..#....#....# ...#.#..#....#....# ####.#..#.####.#### #....#..#.#....#... #....#..#.#....#.G. #..#.#..#.#..#.#..# ####.####.####.#### .#.#.#.#.#.#.#.#.#. #.#.#.#.#.#.#.#.#.# .#.#.#.#.#.#.#.#.#. [出力例] 3370031 ※ 整数 H, W が, 問題文の制約条件から範囲外であるケース. |
■参照サイト
AtCoder Beginner Contest 020