Dijkstra 法をしたけど、同じ殴りなら Warshall--Floyd 法にすればよかった。
問題概要
100 階建ての 2 つの建物 A, B がある。
- A, B 内では 1 フロア上下するのに 秒を要する
- A の 階と B の 階とが廊下でつながっていて、移動に 秒を要する
- A の 階と B の 階とが廊下でつながっていて、移動に 秒を要する
建物 A の 階から建物 B の 階へ移動するのに要する最小時間を求めよ。
解法 (1):算数
ややこしいのが、同一建物内での上下移動をするよりも、廊下の移動を繰り返すのがよい場合がある。
しかしながら、廊下の使用回数が中途半端になるケースは考えなくて大丈夫。よって、以下のいずれかの場合のみ考えれば OK。
- 最初に B の 階へと移動して、B 内での上下移動で到達する場合
- 最初に B の 階へと移動して、B 内での上下移動で到達する場合
- 廊下移動のみで到達する場合
- のとき、 回の廊下移動で到達できる
- のとき、 回の廊下移動で到達できる
#include <bits/stdc++.h> using namespace std; template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; } template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; } int main() { long long A, B, X, Y; cin >> A >> B >> X >> Y; --A, --B; long long res = X + Y * abs(B-A); if (A > 0) chmin(res, X + Y * abs(B-(A-1))); if (A > B) chmin(res, X * ((A-B)*2-1)); else chmin(res, X * ((B-A)*2+1)); cout << res << endl; }
解法 (2):Floyd--Warshall 法
場合分けが怖かったので Dijkstra 法をしたのだけど、Floyd--Warshall 法の方が早いね。 として なので十分間に合う。
#include <bits/stdc++.h> using namespace std; template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; } template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; } const long long INF = 1LL<<60; int main() { long long A, B, X, Y; cin >> A >> B >> X >> Y; --A, --B; vector<vector<long long>> dp(200, vector<long long>(200, INF)); for (int u = 0; u < 100; ++u) { if (u != 99) { dp[u][u+1] = dp[u+1][u] = Y; dp[u+100][u+101] = dp[u+101][u+100] = Y; } dp[u][u+100] = dp[u+100][u] = X; if (u > 0) dp[u][u+99] = dp[u+99][u] = X; dp[u][u] = 0; } for (int k = 0; k < 200; ++k) for (int i = 0; i < 200; ++i) for (int j = 0; j < 200; ++j) chmin(dp[i][j], dp[i][k] + dp[k][j]); cout << dp[A][B+100] << endl; }