https://atcoder.jp/contests/joi2017yo/tasks/joi2017yo_f
解説
https://atcoder.jp/contests/joi2017yo/submissions/8142007
パット見てダイクストラ感はある。
状態を考えると、(どの部屋にいるか, 寒すぎる・暑すぎるのどっちが最後か, 寒すぎる・暑すぎるを出てから何分)が状態となりそう。
これは4*106であり、ダイクストラするにはちょっと危なそう。
だが、AtCoderの実行時間制限を見ると10sなので、ちょっとの無茶はできる。
実装してみる価値はありそうだ。
注意点としては、状態の何分かはX分より大きい時間は意味を持たないので、その場合は上限のXとしてまとめる。
int N, M, X; int T[10101]; vector<pair<int, int>> E[10101]; int dist[10101][3][201]; bool vis[10101][3][201]; //--------------------------------------------------------------------------------------------------- void _main() { cin >> N >> M >> X; rep(i, 0, N) cin >> T[i]; rep(i, 0, M) { int a, b, c; cin >> a >> b >> c; a--; b--; E[a].push_back({ b, c }); E[b].push_back({ a, c }); } rep(i, 0, N) rep(lst, 0, 3) rep(x, 0, X + 1) dist[i][lst][x] = inf; min_priority_queue<pair<int, pair<int,int>>> que; que.push({ 0, {0, 0} }); dist[0][0][0] = 0; while (!que.empty()) { auto q = que.top(); que.pop(); int cst = q.first; int cu = q.second.first / 10; int lst = q.second.first % 10; int x = q.second.second; if (vis[cu][lst][x]) continue; vis[cu][lst][x] = true; fore(p, E[cu]) { int to = p.first; int len = p.second; if (T[to] == 0) { if (lst == 2 and x + len < X) continue; if (chmin(dist[to][0][0], dist[cu][lst][x] + len)) { que.push({ dist[to][0][0], {to * 10 + 0, 0} }); } } else if (T[to] == 1) { int x2 = min(X, x + len); if (chmin(dist[to][lst][x2], dist[cu][lst][x] + len)) { que.push({ dist[to][lst][x2], {to * 10 + lst, x2} }); } } else { if (lst == 0 and x + len < X) continue; if (chmin(dist[to][2][0], dist[cu][lst][x] + len)) { que.push({ dist[to][2][0], {to * 10 + 2, 0} }); } } } } int ans = inf; rep(lst, 0, 3) rep(x, 0, X + 1) chmin(ans, dist[N - 1][lst][x]); cout << ans << endl; }