AOJ1318 long distance taxi
問題ページ
Long Distance Taxi | Aizu Online Judge
解法
拡張dijkstraをする。ガソリン量を10倍して1km/Lと考えると楽。
d[都市][残っているガソリン量] としてdijkstraをする。頂点がO(都市数*ガソリン量)で遷移がO(都市数)なので解ける。
入力が面倒だったり10km/Lだったり面倒だけど典型的な拡張dijkstra
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; #define int ll using VI = vector<int>; using VVI = vector<VI>; using PII = pair<int, int>; #define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i) #define REP(i, n) FOR(i, 0, n) #define ALL(x) x.begin(), x.end() #define PB push_back const ll LLINF = (1LL<<60); const int INF = (1LL<<30); const int MOD = 1000000007; template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); } template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); } template <typename T> bool IN(T a, T b, T x) { return a<=x&&x<b; } template<typename T> T ceil(T a, T b) { return a/b + !!(a%b); } template<class S,class T> ostream &operator <<(ostream& out,const pair<S,T>& a){ out<<'('<<a.first<<','<<a.second<<')'; return out; } template<class T> ostream &operator <<(ostream& out,const vector<T>& a){ out<<'['; REP(i, a.size()) {out<<a[i];if(i!=a.size()-1)out<<',';} out<<']'; return out; } int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}; vector<PII> g[6010]; int d[6010][2010]; signed main(void) { cin.tie(0); ios::sync_with_stdio(false); while(true) { int n, m, cap; cin >> n >> m >> cap; cap *= 10; if(!n) break; string src, dst; cin >> src >> dst; int V = 0; map<string,int> mp; REP(i, 6010) g[i].clear(); REP(i, n) { int l; string s, t; cin >> s >> t >> l; if(mp.find(s) == mp.end()) { mp[s] = V++; } if(mp.find(t) == mp.end()) { mp[t] = V++; } g[mp[s]].PB({mp[t], l}); g[mp[t]].PB({mp[s], l}); // cout << mp[s] << " " << mp[t] << " " << l << endl; } VI exist(V, 0); REP(i, m) { string s; cin >> s; exist[mp[s]] = 1; } int start = mp[src], goal = mp[dst]; // cout << V << endl; REP(i, V) REP(j, cap+1) d[i][j] = LLINF; d[start][cap] = 0; priority_queue<VI, VVI, greater<VI>> que; que.push({d[start][cap], start, cap}); while(que.size()) { VI v = que.top(); que.pop(); // cout << v << endl; int dist = v[0], place = v[1], gas = v[2]; if(dist > d[place][gas]) continue; for(PII &p: g[place]) { int rest = exist[p.first]?cap:gas-p.second; if(gas >= p.second && d[p.first][rest] > d[place][gas] + p.second) { d[p.first][rest] = d[place][gas] + p.second; que.push({d[p.first][rest], p.first, rest}); } } } int ans = LLINF; REP(i, cap+1) chmin(ans, d[goal][i]); if(ans==LLINF) cout << -1 << endl; else cout << ans << endl; } return 0; }