Ranking (as of 2014-10-20): 67 out of 381
Language: C++
/* UVa 10389 - Subway To build using Visual Studio 2012: cl -EHsc -O2 UVa_10389_Subway.cpp */ #include <iostream> #include <iomanip> #include <string> #include <sstream> #include <vector> #include <set> #include <limits> #include <cmath> #include <cstdlib> using namespace std; struct point { int x_, y_; int sl_; // subway line number int ss_; // subway station number }; double euclidean_distance(const point& a, const point& b) { double dx = a.x_ - b.x_, dy = a.y_ - b.y_; return sqrt(dx * dx + dy * dy); } struct edge { int v_; double w_; edge() {} edge(int v, double w) : v_(v), w_(w) {} }; struct distance_comparator { vector<double>& distances_; distance_comparator(vector<double>& distances) : distances_(distances) {} bool operator() (const int i, const int j) const { if (distances_[i] != distances_[j]) return distances_[i] < distances_[j]; else return i < j; } }; int main() { string line; istringstream iss; getline(cin, line); iss.str(line); int nr_cases; iss >> nr_cases; iss.clear(); getline(cin, line); // skip a blank line while (nr_cases--) { getline(cin, line); iss.str(line); vector<point> points; point s, e; s.sl_ = 0; e.sl_ = 1; s.ss_ = e.ss_ = -1; iss >> s.x_ >> s.y_ >> e.x_ >> e.y_; points.push_back(s); points.push_back(e); iss.clear(); for (int sl = 2; getline(cin, line) && !line.empty(); sl++) { iss.str(line); point p; p.sl_ = sl; for (int ss = 0; ; ss++) { iss >> p.x_ >> p.y_; if (p.x_ == -1) break; p.ss_ = ss; points.push_back(p); } iss.clear(); } const double walk = 10000.0 / 60.0, subway = 40000.0 / 60.0; int n = static_cast<int>(points.size()); vector< vector<edge> > edges(n); for (int i = 0; i < n - 1; i++) for (int j = i + 1; j < n; j++) { double d; if (points[i].sl_ == points[j].sl_) { // two points are on the same subway line if (abs(points[i].ss_ - points[j].ss_) == 1) { // station i and station j are adjacent d = euclidean_distance(points[i], points[j]) / subway; edges[i].push_back(edge(j, d)); edges[j].push_back(edge(i, d)); } } // else { d = euclidean_distance(points[i], points[j]) / walk; edges[i].push_back(edge(j, d)); edges[j].push_back(edge(i, d)); // } } // apply Dijkstra's shortest path vector<double> distances(n, numeric_limits<double>::max()); vector<bool> visited(n, false); set<int, distance_comparator> pq(distances); // priority queue distances[0] = 0.0; pq.insert(0); while (!pq.empty()) { int u = *pq.begin(); pq.erase(pq.begin()); visited[u] = true; if (u == 1) break; const vector<edge>& es = edges[u]; for (size_t i = 0, j = es.size(); i < j; i++) { const edge& e = es[i]; if (!visited[e.v_] && distances[e.v_] > distances[u] + e.w_) { pq.erase(e.v_); // remove vt if it has already been in the queue // this must be done before updating distances[] distances[e.v_] = distances[u] + e.w_; pq.insert(e.v_); } } } cout << fixed << setprecision(0) << distances[1] << endl; if (nr_cases) cout << endl; } return 0; }
No comments:
Post a Comment