【題解】UVA 12661 Funny Car Racing

Browse Problem: https://vjudge.net/problem/UVA-12661

摘錄翻譯:
在一個有n個交叉路口和m條道路的城市中,有一個趣味賽車活動。

有趣的是:每條道路會定期開放和封閉。 每條道路都有兩個整數參數(a,b),表示這條道路將開放a秒鐘,然後封閉b秒,然後開放a秒鐘… 時間從比賽開始時計算。 您必須在道路開放時進入道路,並且在道路關閉前離開它。目標是從路口s出發,並儘早抵達路口t。

注意:道路是單向的。
注意:即使所有相鄰道路都封閉時,也可以在路口等候。
注意:沒有道路的兩端是同一個路口,但兩個路口可能有多種連結方式。

解題想法:使用Dijkstra計算最短路徑。

#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <utility>
using namespace std;
#define maxn 305

struct node{
    int v;
    long long a, b, t;
    node(int _v, long long _a, long long _b, long long _t): v(_v), a(_a), b(_b), t(_t) {}
};
// 存圖
vector<node> g[maxn];
// 紀錄該點是否已找到最短距離且向外拓展過
int exp[maxn];
// 紀錄起點到此點的最短距離,初始設為INF,起點設成0
long long dist[maxn];

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int n, m, src, dst;
    int u, v;
    long long a, b, t;
    int Case = 1;
    
    while (cin >> n >> m >> src >> dst) {
        memset(exp, 0, sizeof(exp));
        memset(dist, 0x3F, sizeof(dist));
        for (int i=0; i<maxn; i++){
            g[i].clear();
        }
        dist[src] = 0;
        for (int i=0; i<m; i++) {
            cin >> u >> v >> a >> b >> t;
            if (a >= t) g[u].push_back(node(v, a, b, t));
        }
        // Dijkstra
        set<pair<long long,int> > st; // 記錄尚未拓展的節點的最新狀態
        st.insert({0, src});
        long long Time=0, new_Time=0;
        int cur = -1;
        while (!st.empty()){
            auto now = *st.begin();
            st.erase(now);
            if (exp[now.second]) continue;
            Time = now.first;
            cur = now.second;
            for (auto nxt : g[cur]){
                if (Time % (nxt.a + nxt.b) <= (nxt.a - nxt.t)){
                    new_Time = Time + nxt.t;
                }else{
                    new_Time = Time + nxt.a + nxt.b - (Time % (nxt.a + nxt.b)) + nxt.t;
                }
                if (new_Time < dist[nxt.v]){
                    st.erase({dist[nxt.v], nxt.v});
                    dist[nxt.v] = new_Time;
                    st.insert({dist[nxt.v], nxt.v});
                }
            }
            exp[cur] = 1;
        }
        cout << "Case " << Case++ << ": ";
        cout << dist[dst] << '\n';
    }
    return 0;
}

分享本文 Share with friends