#include #include #include #include #include #include #include #include using namespace std; class DICTIONARY { private: map city2number; vector number2city; public: int City2Number(const string& city){ map::iterator it = city2number.find(city); if (it == city2number.end()){ int number = (int)number2city.size(); number2city.push_back(city); city2number.insert(make_pair(city, number)); return number; } return it->second; } const string& Number2City(int number)const{ return number2city[number]; } int GetCount()const{ return (int)number2city.size(); } void Clear(){ city2number.clear(); number2city.clear(); } }; struct DATA{ int start; int goal; int price; bool IsWarosuThan(const DATA& rh)const{ return start <= rh.start && goal >= rh.goal && price >= rh.price; } }; class EraseData : public unary_function { private: const DATA &data; public: EraseData(const DATA& d) : data(d){} bool operator()(const DATA& rh)const{ return rh.IsWarosuThan(data); } }; class CheckData : public unary_function { private: const DATA &data; public: CheckData(const DATA& d) : data(d){} bool operator()(const DATA& rh)const{ return data.IsWarosuThan(rh); } }; main() { int n; while (cin >> n && n){ DICTIONARY dic; vector graph[100][100]; for (int i = 0; i < n; ++i){ string start_city, arrival_city; int start_h, start_m; int arrival_h, arrival_m; int price; char c; cin >> start_city >> start_h >> c >> start_m >> arrival_city >> arrival_h >> c >> arrival_m >> price; int start_number = dic.City2Number(start_city); int arrival_number = dic.City2Number(arrival_city); int start_time = start_h * 60 + start_m; int arrival_time = arrival_h * 60 + arrival_m; if (start_time < 8 * 60 || 18 * 60 < arrival_time){ continue; } DATA data; data.start = start_time; data.goal = arrival_time; data.price = price; graph[start_number][arrival_number].push_back(data); } int N = dic.GetCount(); for (int via = 0; via < N; ++via){ for (int from = 0; from < N; ++from){ //if (via == from)continue; for (int to = 0; to < N; ++to){ //if (via == to || from == to)continue; for (vector::iterator it_from = graph[from][via].begin(); it_from != graph[from][via].end(); ++it_from){ for (vector::iterator it_to = graph[via][to].begin(); it_to != graph[via][to].end(); ++it_to){ if (it_from->goal > it_to->start){ continue; } DATA data; data.start = it_from->start; data.goal = it_to->goal; data.price = it_from->price + it_to->price; vector& route = graph[from][to]; //cout << route.size() << endl; //cerr << from << " " << via << " " << to << " " << data.price << endl; route.erase(remove_if(route.begin(), route.end(), EraseData(data)), route.end()); if (find_if(route.begin(), route.end(), CheckData(data)) == route.end()){ //cerr << (int)route.size() << endl;; //cerr << "debug" << endl; route.push_back(data); } } } } } } //cerr << "Hello" << endl; int hakodate = dic.City2Number("Hakodate"); int tokyo = dic.City2Number("Tokyo"); int answer = INT_MAX; for (int city = 0; city < N; ++city){ if (city == hakodate || city == tokyo)continue; for (vector::iterator it_h_go = graph[hakodate][city].begin(); it_h_go != graph[hakodate][city].end(); ++it_h_go){ for (vector::iterator it_t_go = graph[tokyo][city].begin(); it_t_go != graph[tokyo][city].end(); ++it_t_go){ for (vector::iterator it_h_back = graph[city][hakodate].begin(); it_h_back != graph[city][hakodate].end(); ++it_h_back){ if (it_h_go->goal + 30 > it_h_back->start || it_t_go->goal + 30 > it_h_back->start){ continue; } for (vector::iterator it_t_back = graph[city][tokyo].begin(); it_t_back != graph[city][tokyo].end(); ++it_t_back){ if (it_h_go->goal + 30 > it_t_back->start || it_t_go->goal + 30 > it_t_back->start){ continue; } int price = it_h_go->price + it_h_back->price + it_t_go->price + it_t_back->price; answer = min(answer, price); } } } } } for (vector::iterator it_go = graph[tokyo][hakodate].begin(); it_go != graph[tokyo][hakodate].end(); ++it_go){ for (vector::iterator it_back = graph[hakodate][tokyo].begin(); it_back != graph[hakodate][tokyo].end(); ++it_back){ if (it_go->goal + 30 > it_back->start){ continue; } int price = it_go->price + it_back->price; answer = min(answer, price); } } for (vector::iterator it_go = graph[hakodate][tokyo].begin(); it_go != graph[hakodate][tokyo].end(); ++it_go){ for (vector::iterator it_back = graph[tokyo][hakodate].begin(); it_back != graph[tokyo][hakodate].end(); ++it_back){ if (it_go->goal + 30 > it_back->start){ continue; } int price = it_go->price + it_back->price; answer = min(answer, price); } } if (answer == INT_MAX){ answer = 0; } cout << answer << endl; } }