#include #include #include #include #include #include #include #include using namespace std; const int begin_time = 8 * 60; const int end_time = (12 + 6) * 60; const int INFINITY = 10000 * 2000 + 1; map town; int getTownId(const string& t) { map::iterator i = town.find(t); if(i != town.end()) return i->second; int id = town.size(); town[t] = id; return id; } int parseTime(const string& str) { int h, m; istringstream iss(str); iss >> h; iss.get(); iss >> m; return h * 60 + m; } struct Train { int from, to; int leave, arrive; int cost; friend istream& operator >>(istream& s, Train& t) { string from, to, l, a; s >> from >> l >> to >> a >> t.cost; t.from = getTownId(from); t.to = getTownId(to); t.leave = parseTime(l); t.arrive = parseTime(a); return s; } }; int n; int m; Train train[2048]; vector trG[128]; vector trR[128]; struct State { int time; int cost; State() {} State(int t, int c) : time(t), cost(c) {} bool isAbsoluteLessEq(const State& b) const { return time <= b.time && cost <= b.cost; } bool isAbsoluteLessEqInv(const State& b) const { return time >= b.time && cost <= b.cost; } bool operator <(const State& b) const { if(time != b.time) return time < b.time; return cost < b.cost; } }; vector go[2][128]; vector ret[2][128]; void Calc(int start, bool r) { vector > up; State init(begin_time, 0); if(r) init.time = end_time; up.push_back(make_pair(start, init)); while(!up.empty()) { int p = up.back().first; State s = up.back().second; up.pop_back(); vector& cur = (r) ? ret[start][p] : go[start][p]; for(int i = 0; i < (int)cur.size(); ++i) if((r && cur[i].isAbsoluteLessEqInv(s)) || (!r && cur[i].isAbsoluteLessEq(s))) { p = -1; break; } if(p < 0) continue; cur.push_back(s); vector& tr = (r) ? trR[p] : trG[p]; for(int i = 0; i < (int)tr.size(); ++i) { Train& t = tr[i]; if(r) { if(s.time >= t.arrive) { up.push_back(make_pair(t.from, State(t.leave, s.cost + t.cost))); } } else { if(s.time <= t.leave) { up.push_back(make_pair(t.to, State(t.arrive, s.cost + t.cost))); } } } } } /* inline int GetCost(State& g1, State& g2, State& r1, State& r2) { int t = max(g1.time, g2.time) + 30; if(t <= r1.time && t <= r2.time) return g1.cost + g2.cost + r1.cost + r2.cost; return INFINITY; } int GetCost(int meet) { int r = INFINITY; vector& g1 = go[0][meet]; vector& g2 = go[1][meet]; vector& r1 = ret[0][meet]; vector& r2 = ret[1][meet]; for(int i = 0; i < (int)g1.size(); ++i) for(int j = 0; j < (int)g2.size(); ++j) for(int k = 0; k < (int)r1.size(); ++k) for(int l = 0; l < (int)r2.size(); ++l) r = min(r, GetCost(g1[i], g2[j], r1[k], r2[l])); return r; } */ struct TimeLess { bool operator ()(const State& a, const State& b) const { return a.time < b.time; } }; int GetCost(int meet) { int r = INFINITY; vector& g1 = go[0][meet]; vector& g2 = go[1][meet]; vector& r1 = ret[0][meet]; vector& r2 = ret[1][meet]; g1.push_back(State(end_time + 1, INFINITY)); g2.push_back(State(end_time + 1, INFINITY)); r1.push_back(State(end_time + 1, INFINITY)); r2.push_back(State(end_time + 1, INFINITY)); r1.push_back(State(begin_time - 1, INFINITY)); r2.push_back(State(begin_time - 1, INFINITY)); sort(g1.begin(), g1.end(), TimeLess()); sort(g2.begin(), g2.end(), TimeLess()); sort(r1.begin(), r1.end(), TimeLess()); sort(r2.begin(), r2.end(), TimeLess()); int i, j, k, l; int c1, c2, c3, c4; i = j = 0; c1 = c2 = c3 = c4 = INFINITY; k = r1.size()-1; l = r2.size()-1; for(int t = end_time; t >= begin_time; --t) { while(t <= r1[k].time) { if(r1[k].time <= end_time) { c3 = min(c3, r1[k].cost); r1[k].cost = c3; } --k; } while(t <= r2[l].time) { if(r2[l].time <= end_time) { c4 = min(c4, r2[l].cost); r2[l].cost = c4; } --l; } } k = l = 0; c3 = c4 = INFINITY; for(int t = begin_time; t <= end_time-30; ++t) { while(t >= g1[i].time) c1 = min(c1, g1[i++].cost); while(t >= g2[j].time) c2 = min(c2, g2[j++].cost); while(t+30 > r1[k].time) c3 = r1[++k].cost; while(t+30 > r2[l].time) c4 = r2[++l].cost; r = min(r, c1 + c2 + c3 + c4); } return r; } void Init() { town.clear(); town["Hakodate"] = 0; town["Tokyo"] = 1; for(int i = 0; i < 128; ++i) { trG[i].clear(); trR[i].clear(); go[0][i].clear(); go[1][i].clear(); ret[0][i].clear(); ret[1][i].clear(); } } int main() { while(cin >> m && m) { Init(); for(int i = 0; i < m; ++i) { Train& r = train[i]; cin >> r; trG[r.from].push_back(r); trR[r.to].push_back(r); } n = town.size(); Calc(0, false); Calc(1, false); Calc(0, true); Calc(1, true); /*for(int i = 0; i < (int)town.size(); ++i) { vector& s = ret[0][i]; cout << i << endl; for(int j = 0; j < (int)s.size(); ++j) { cout << s[j].time << " " << s[j].cost << endl; } }*/ int ans = INFINITY; for(int i = 0; i < n; ++i) { //cout << i << " " << GetCost(i) << endl; ans = min(ans, GetCost(i)); } if(ans >= INFINITY) ans = 0; cout << ans << endl; } }