Problem:
Problem C:
Dig or Climb
Benjamin Forest VIII is a king of a country. One of his best friends Nod lives in a village far from
his castle. Nod gets seriously sick and is on the verge of death. Benjamin orders his subordinate
Red to bring good medicine for him as soon as possible. However, there is no road from the
castle to the village. Therefore, Red needs to climb over mountains and across canyons to reach
the village. He has decided to get to the village on the shortest path on a map, that is, he will
move on the straight line between the castle and the village. Then his way can be considered as
polyline with
n
points (
x
1
,
y
1
) . . . (
x
n
,
y
n
) as illustlated in the following figure.
Figure 1: An example route from the castle to the village
Here,
x
i
indicates the distance between the castle and the point
i
, as the crow flies, and
y
i
indicates the height of the point
i
. The castle is located on the point (
x
1
,
y
1
), and the village is
located on the point (
x
n
,
y
n
).
Red can walk in speed
v
w
. Also, since he has a skill to cut a tunnel through a mountain
horizontally, he can move inside the mountain in speed
v
c
.
Your job is to write a program to the minimum time to get to the village.
Input
The input is a sequence of datasets. Each dataset is given in the following format:
n
v
w
v
c
x
1
y
1
...
x
n
y
n
You may assume all the following:
n
≤ 1,000, 1 ≤
v
w
,
v
c
≤ 10, -10,000 ≤
x
i
,
y
i
≤ 10,000, and
x
i
<
x
j
for all
i
<
j
.
The input is terminated in case of
n
= 0. This is not part of any datasets and thus should not
be processed.
Output
For each dataset, you should print the minimum time required to get to the village in a line.
Each minimum time should be given as a decimal with an arbitrary number of fractional digits
and with an absolute error of at most 10
-6
. No extra space or character is allowed.
Sample Input
3
2 1
0 0
50 50
100 0
3
1 1
0 0
50 50
100 0
3
1 2
0 0
50 50
100 0
3
2 1
0 0
100 100
150 50
6
1 2
0 0
50 50
100 0
150 0
200 50
250 0
0
Output for the Sample Input
70.710678
100.000000
50.000000
106.066017
150.000000

Submitted solutions:

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
#include <map>
#include <queue>
using namespace std;
const double EPS = 1e-6;
const double INF = 1e12;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};

namespace std{
    bool operator < (const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(abs(c)-abs(b) > EPS) return -2; //a-b-c
    return 0; //a-c-b
}

bool intersectSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) <= 0 ) &&
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) <= 0 );
}
bool intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS  && dot(s[0]-p, s[1]-p)<EPS;
}

bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1]-l[0], m[1]-m[0]);
  double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B/A *(m[1]-m[0]);
}

int in_poly(const P &p, const VP &poly){
    int n = poly.size();
    int ret = -1;
    for(int i=0; i<n; i++){
        P a = poly[i]-p;
        P b = poly[(i+1)%n]-p;
        if(a.Y > b.Y) swap(a,b);
        if(intersectSP(L(a,b), P(0,0))) return 0;
        if(a.Y<=0 && b.Y>0 && cross(a,b)<0) ret = -ret;
    }
    return ret;
}

pair<vector<vector<int> >, VP> arrangement(const vector<L> &l){
    vector<VP> cp(l.size());
    VP plist;
    for(int i=0; i<(int)l.size(); i++){
        for(int j=i+1; j<(int)l.size(); j++){
            if(!isParallel(l[i], l[j]) && intersectSS(l[i], l[j])){
                P cpij = crosspointLL(l[i], l[j]);
                cp[i].push_back(cpij);
                cp[j].push_back(cpij);
                plist.push_back(cpij);
            }
        }
        cp[i].push_back(l[i][0]);
        cp[i].push_back(l[i][1]);
        plist.push_back(l[i][0]);
        plist.push_back(l[i][1]);
        sort(cp[i].begin(), cp[i].end());
        cp[i].erase(unique(cp[i].begin(), cp[i].end()), cp[i].end());
    }
    sort(plist.begin(), plist.end());
    plist.erase(unique(plist.begin(), plist.end()), plist.end());

    int n = plist.size();
    map<P, int> conv;
    for(int i=0; i<n; i++){
        conv[plist[i]] = i;
    }
    vector<vector<int> > adj(n);
    for(int i=0; i<(int)cp.size(); i++){
        for(int j=0; j<(int)cp[i].size()-1; j++){
            int jidx = conv[cp[i][j]];
            int jp1idx = conv[cp[i][j+1]];
            adj[jidx].push_back(jp1idx);
            adj[jp1idx].push_back(jidx);
        }
    }
    for(int i=0; i<n; i++){
        sort(adj[i].begin(), adj[i].end());
        adj[i].erase(unique(adj[i].begin(), adj[i].end()), adj[i].end());
    }
    return make_pair(adj, plist);
}


int main(){
    while(1){
        int n;
        cin >> n;
        if(n == 0) break;

        double vw,vc;
        cin >> vw >> vc;
        VP p(n);
        for(int i=0; i<n; i++){
            double x,y;
            cin >> x >> y;
            p[i] = P(x, y);
        }
        double xmin = p[0].X, xmax = p[n-1].X;
        VP poly = p;
        reverse(poly.begin(), poly.end());
        poly.push_back(P(xmin, -2e4));
        poly.push_back(P(xmax, -2e4));

        vector<L> l;
        for(int i=0; i<n; i++){
            if(i != n-1){
                l.push_back(L(p[i], p[i+1]));
            }
            double y = p[i].Y;
            L cut(P(xmin, y), P(xmax, y));
            VP cp;
            for(int j=0; j<n-1; j++){
                L edge(p[j], p[j+1]);
                if(!isParallel(cut, edge) && intersectSS(cut, edge)){
                    cp.push_back(crosspointLL(cut, edge));
                }
            }
            cp.erase(unique(cp.begin(), cp.end()), cp.end());
            int idx = lower_bound(cp.begin(), cp.end(), p[i]) -cp.begin();
            if(idx == (int)cp.size() || !(cp[idx] == p[i])){
                continue;
            }
            if(i > 0 && p[i-1].Y > p[i].Y +EPS && idx > 0){
                l.push_back(L(cp[idx-1], cp[idx]));
            }
            if(i < n-1 && p[i].Y +EPS < p[i+1].Y && idx < (int)cp.size()-1){
                l.push_back(L(cp[idx], cp[idx+1]));
            }
        }
        sort(l.begin(), l.end());
        l.erase(unique(l.begin(), l.end()), l.end());
        pair<vector<vector<int> >, VP> ret = arrangement(l);
        vector<vector<int> > &adj = ret.first;
        VP &plist = ret.second;

        vector<vector<pair<int, double> > > adj2(adj.size());
        for(int i=0; i<(int)adj.size(); i++){
            adj2[i].resize(adj[i].size());
            for(int j=0; j<(int)adj[i].size(); j++){
                P mid = (plist[i] +plist[adj[i][j]])/2.0;
                double cost;
                if(in_poly(mid, poly) == 1){
                    cost = abs(plist[i] -plist[adj[i][j]]) /vc;
                }else{
                    cost = abs(plist[i] -plist[adj[i][j]]) /vw;
                }
                adj2[i][j] = make_pair(adj[i][j], cost);
            }
        }

        priority_queue<pair<double, int> > wait;
        wait.push(make_pair(0, 0));
        vector<double> mincost(adj2.size(), INF);
        mincost[0] = 0;
        while(!wait.empty()){
            double cost = -wait.top().first;
            int pos = wait.top().second;
            wait.pop();
            if(cost > mincost[pos] +EPS) continue;
            if(pos == (int)adj2.size()-1) break;
            for(int i=0; i<(int)adj2[pos].size(); i++){
                int npos = adj2[pos][i].first;
                double ncost = cost +adj2[pos][i].second;
                if(ncost +EPS < mincost[npos]){
                    mincost[npos] = ncost;
                    wait.push(make_pair(-ncost, npos));
                }
            }
        }
        cout << fixed << setprecision(10);
        cout << mincost[adj2.size()-1] << endl;
    }    
    return 0;
}
accuracy: 1
time_ms: 620
memory_kb: 3860
final_rank: 15

code_snippet: #define _USE_MATH_DEFINES
#define INF 0x3f3f3f3f
#include <cstdio>
#include <iostream>
#include <sstream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <limits>
#include <map>
#include <string>
#include <cstring>
#include <set>
#include <deque>
#include <bitset>
#include <list>
#include <cctype>
#include <utility>
#include <complex>
#include <assert.h>
 
using namespace std;
 
typedef long long ll;
typedef pair <double,double> P;
 
static const int tx[] = {+0,+1,+0,-1};
static const int ty[] = {-1,+0,+1,+0};
 
static const double EPS = 1e-8;

typedef complex<double> Point;

namespace std {
  bool operator < (const Point& a, const Point& b) {
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}

double cross(const Point& a, const Point& b) {
  return imag(conj(a)*b);
}
double dot(const Point& a, const Point& b) {
  return real(conj(a)*b);
}

struct Line : public vector<Point> {
  Line(const Point &a, const Point &b) {
    push_back(a); push_back(b);
  }
};

int ccw(Point a, Point b, Point c) {
  b -= a; c -= a;
  if (cross(b, c) > 0)   return +1;       // counter clockwise
  if (cross(b, c) < 0)   return -1;       // clockwise
  if (dot(b, c) < 0)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}

bool intersectSS(const Line &s, const Line &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
    ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}

Point crosspoint(const Line &l, const Line &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

double compute_area(const Point &l,const Point &m){
  return abs(cross(l,m)) / 2.0;
}

bool is_equal(const Point &l,const Point &m){
  return ((abs(real(l) - real(m)) < EPS) && (abs(imag(l) - imag(m) < EPS)));
}

class State {
public:
  int pos;
  double cost;
  State(int pos,double cost) :
    pos(pos), cost(cost) {}
  bool operator<(const State& s) const {
    return cost < s.cost;
  }
  bool operator>(const State& s) const {
    return cost > s.cost;
  }
};

double dp[3001];
vector<State> costs[3001];

int main(){
  int n;
  while(~scanf("%d",&n)){
    if(n == 0) break;

    double vw,vc;    
    scanf("%lf %lf",&vw,&vc);
    vector<Point> points;
    for(int i = 0; i < n; i++){
      double x,y;
      scanf("%lf %lf",&x,&y);
      points.push_back(Point(x,y));
    }

    for(int i = 0; i <= 2000; i++){
      dp[i] = 1e10;
      costs[i].clear();
    }
    vector<double> x;
    for(int i = 0; i < n; i++){
      x.push_back(points[i].real());
      Line here2right(points[i],Point(1e10,points[i].imag()));
      for(int j = i + 1; j + 1 < n; j++){
        if(points[i].imag() + EPS >= points[j].imag()) break;
        Line target(points[j],points[j+1]);
        if(intersectSS(here2right,target)){
          x.push_back(crosspoint(here2right,target).real());
          break;
        }
      }

      Line here2left(Point(-1e10,points[i].imag()),points[i]);
      for(int j = i - 1; j - 1 >= 0; j--){
        if(points[i].imag() + EPS >= points[j].imag()) break;
        Line target(points[j-1],points[j]);
        if(intersectSS(here2left,target)){
          x.push_back(crosspoint(here2left,target).real());
          break;
        }
      }
    }
    sort(x.begin(),x.end());
    x.erase(unique(x.begin(),x.end()),x.end());

    for(int i = 0; i < n; i++){
      int from = lower_bound(x.begin(),x.end(),points[i].real() - EPS) - x.begin();
      if(i + 1 < n){
        int to = lower_bound(x.begin(),x.end(),points[i+1].real() - EPS) - x.begin();  
        costs[from].push_back(State(to,abs(points[i+1]-points[i])/vw));
        costs[to].push_back(State(from,abs(points[i+1]-points[i])/vw));
      }
      Line here2right(points[i],Point(1e10,points[i].imag()));
      for(int j = i + 1; j + 1 < n; j++){
        if(points[i].imag() + EPS >= points[j].imag()) break;
        Line target(points[j],points[j+1]);
        if(intersectSS(here2right,target)){
          Point p = crosspoint(here2right,target);
          int lhs = lower_bound(x.begin(),x.end(),points[j].real() - EPS) - x.begin();  
          int mid = lower_bound(x.begin(),x.end(),p.real() - EPS) - x.begin();
          int rhs = lower_bound(x.begin(),x.end(),points[j+1].real() - EPS) - x.begin();  

          costs[from].push_back(State(mid,abs(p - points[i])/vc));
          costs[mid].push_back(State(from,abs(p - points[i])/vc));

          costs[lhs].push_back(State(mid,abs(p - points[j])/vw));
          costs[mid].push_back(State(rhs,abs(p - points[j+1])/vw));

          costs[mid].push_back(State(lhs,abs(p - points[j])/vw));
          costs[rhs].push_back(State(mid,abs(p - points[j+1])/vw));
          break;
        }
      }

      Line here2left(Point(-1e10,points[i].imag()),points[i]);
      for(int j = i - 1; j - 1 >= 0; j--){
        if(points[i].imag() + EPS >= points[j].imag()) break;
        Line target(points[j-1],points[j]);
        if(intersectSS(here2left,target)){
          Point p = crosspoint(here2left,target);
          int rhs = lower_bound(x.begin(),x.end(),points[j].real() - EPS) - x.begin();  
          int mid = lower_bound(x.begin(),x.end(),p.real() - EPS) - x.begin();
          int lhs = lower_bound(x.begin(),x.end(),points[j-1].real() - EPS) - x.begin();  

          costs[from].push_back(State(mid,abs(p - points[i])/vc));
          costs[mid].push_back(State(from,abs(p - points[i])/vc));

          costs[rhs].push_back(State(mid,abs(p - points[j])/vw));
          costs[mid].push_back(State(rhs,abs(p - points[j])/vw));

          costs[mid].push_back(State(lhs,abs(p - points[j-1])/vw));
          costs[lhs].push_back(State(mid,abs(p - points[j-1])/vw));
          break;
        }
      }
    }
    
    int goal_pos = x.size() - 1;
    dp[0] = 0.0;
    priority_queue<State,vector<State>,greater<State> > que;
    que.push(State(0,0));

    while(!que.empty()){
      State s = que.top();
      que.pop();
      if(s.pos == goal_pos) break;

      for(int i = 0; i < costs[s.pos].size(); i++){
        int next_pos = costs[s.pos][i].pos;
        double next_cost = costs[s.pos][i].cost;
        if(dp[next_pos] > s.cost + next_cost){
          dp[next_pos] = s.cost + next_cost;
          que.push(State(next_pos,s.cost + next_cost));
        }
      }
    }
    printf("%.7lf\n",dp[goal_pos]);
  }
}
accuracy: 1
time_ms: 100
memory_kb: 1572
final_rank: 11

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-7)
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;

const int IINF = INT_MAX;

// Library - template - begin

class Point{
public:
  double x,y;
  Point(double x = -IINF,double y = -IINF): x(x),y(y){}
  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:y<p.y; }
};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
};

typedef Point Vector;
typedef Segment Line;

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }
double norm(Point a){ return a.x*a.x+a.y*a.y; }
double abs(Point a){ return sqrt(norm(a)); }

// Library - template - end

// Library - intersect - begin
Point crosspoint(Line l, Line m) {
  double A = cross(l.p2 - l.p1, m.p2 - m.p1);
  double B = cross(l.p2 - l.p1, l.p2 - m.p1);
  if (abs(A) < EPS && abs(B) < EPS) return m.p1; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m.p1 +   (m.p2 - m.p1) * (B / A);
}
// Library - intersect - end

int V;
double vw,vc;
Point ps[1010];
bool here[1010]; // here is the point
double mincost[1010];

inline bool LT(double a,double b) { return !equals(a,b) && a < b; }

int main(){

  while( cin >> V, V ){
    cin >> vw >> vc;
    rep(i,V) cin >> ps[i].x >> ps[i].y;

    rep(i,V) mincost[i] = IINF;
    mincost[0] = 0;
    REP(i,1,V) mincost[i] = mincost[i-1] + abs(ps[i]-ps[i-1]) / vw;

    rep(i,V-2){
      if( !( LT(ps[i].y,ps[i+1].y) ) ) continue;
      double lower = ps[i+1].y;
      REP(k,i+2,V){
        if( !( ps[k-1].y > ps[k].y ) ) {
          lower = min(lower,ps[k].y);
          continue;
        }
        if( ps[k].y < lower ){
          double Y = max(ps[i].y,ps[k].y);
          Line line = Line(Point(-10100,Y),Point(10100,Y));
          Point sp = ps[i], gp = ps[k];
          Point np = crosspoint(line,Line(ps[i  ],ps[i+1]));
          Point mp = crosspoint(line,Line(ps[k-1],ps[k]));
          double dist1 = abs(np-sp);
          double dist3 = abs(np-mp);
          double dist4 = abs(gp-mp);
          double time1 = dist1 / vw + dist3 / vc + dist4 / vw;
          if( LT(mincost[i]+time1,mincost[k]) ){
            mincost[k] = mincost[i]+time1;
            REP(j,k,V) mincost[j] = min(mincost[j],mincost[j-1] + abs(ps[j]-ps[j-1])/vw);
          }
        }
        lower = min(lower,ps[k].y);
        if( lower < ps[i].y ) break; //これ忘れてた
      }
    }
    printf("%.8f\n",mincost[V-1]);
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1272
final_rank: 6

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-7)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;

const int IINF = INT_MAX;

// Library - template - begin

class Point{
public:
  double x,y;

  Point(double x = -IINF,double y = -IINF): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:y<p.y; }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator == (const Segment& p)const { return p.p1 == p1 && p.p2 == p2; }
};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad は角度をラジアンで持たせること
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// 度をラジアンに変換
double toRad(double agl){ return agl*M_PI/180.0; }

// Library - template - end


// Library - ccw - bingin

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

// Library - ccw - end

// Library - intersect - begin

bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}

/*
same lineの時注意
もしm.p1が中心でなかったときに正しい答えとならない
Point crosspoint(Line l,Line m){
  double A = cross(l.p2-l.p1,m.p2-m.p1);
  double B = cross(l.p2-l.p1,l.p2-m.p1);
  if(abs(A) < EPS && abs(B) < EPS){
    vector<Point> vec;
    vec.push_back(l.p1),vec.push_back(l.p2),vec.push_back(m.p1),vec.push_back(m.p2);
    sort(vec.begin(),vec.end());
    assert(vec[1] == vec[2]);
    return vec[1];
    //return m.p1;
  }
  if(abs(A) < EPS)assert(false);
  return m.p1 + (m.p2-m.p1)*(B/A);
}

*/
Point crosspoint(Line l, Line m) {
  double A = cross(l.p2 - l.p1, m.p2 - m.p1);
  double B = cross(l.p2 - l.p1, l.p2 - m.p1);
  if (abs(A) < EPS && abs(B) < EPS) return m.p1; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m.p1 +   (m.p2 - m.p1) * (B / A);
}


// Library - intersect - end

int V;
double vw,vc;
Point ps[1010];
bool here[1010]; // here is the point
double mincost[1010];

// a < b
inline bool LT(double a,double b) { return !equals(a,b) && a < b; }

// a <= b
inline bool LTE(double a,double b) { return equals(a,b) || a < b; }

int main(){

  while( cin >> V, V ){
    cin >> vw >> vc;
    rep(i,V) cin >> ps[i].x >> ps[i].y;

    rep(i,V) mincost[i] = IINF;
    mincost[0] = 0;
    REP(i,1,V) mincost[i] = mincost[i-1] + abs(ps[i]-ps[i-1]) / vw;

    rep(i,V-2){
      if( !( LT(ps[i].y,ps[i+1].y) ) ) continue;
      double lower = ps[i+1].y;
      //cout << "start = " << i << endl;
      REP(k,i+2,V){
        if( !( ps[k-1].y > ps[k].y ) ) {
          //cout << "continue " << k  << endl;
          lower = min(lower,ps[k].y);
          continue;
        }
        if( ps[k].y < lower ){
          double Y = max(ps[i].y,ps[k].y);
          Line line = Line(Point(-10100,Y),Point(10100,Y));
          Point sp = ps[i], gp = ps[k];
          Point np = crosspoint(line,Line(ps[i  ],ps[i+1]));
          Point mp = crosspoint(line,Line(ps[k-1],ps[k]));
          double dist1 = abs(np-sp);
          double dist3 = abs(np-mp);
          double dist4 = abs(gp-mp);
          double time1 = dist1 / vw + dist3 / vc + dist4 / vw;
          //cout << np << " <=> " << mp<<endl;
          //cout << "time1 = " << time1 << " :: " << mincost[i] + time1 << endl;
          if( LT(mincost[i]+time1,mincost[k]) ){
            mincost[k] = mincost[i]+time1;
            REP(j,k,V) mincost[j] = min(mincost[j],mincost[j-1] + abs(ps[j]-ps[j-1])/vw);
          }
        }

        lower = min(lower,ps[k].y);
        if( lower < ps[i].y ) break;
        //if( k == V-1) cout << "BREAK " << k << endl;
      }
    }

    //rep(i,V) cout << mincost[i] << " "; cout << endl;
    printf("%.8f\n",mincost[V-1]);

  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1276
final_rank: 7

code_snippet: #include <algorithm>
#include <bitset>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

#define repi(i,a,b) for(int i = (a); i < (b); i++)
#define rep(i,a) repi(i,0,a)
#define repd(i,a,b) for(int i = (a) ; i >= (b); i--)
#define repit(i,a) for(__typeof((a).begin()) i = (a).begin(); i!= (a).end(); i++)
#define all(u) (u).begin(),(u).end()
#define rall(u) (u).rbegin(),(u).rend()
#define UNIQUE(u) (u).erase(unique(all(u)),(u).end)

#define pb push_back
#define mp makek_pair
#define INF 1e9
#define EPS 1e-9
#define PI acos(-1.0)

using namespace std;

typedef long long ll;
typedef vector<int> vi;

int n, x[1024], y[1024];
double vw, vc;

const int N = 4000;

double mem[N];

struct edge
{
    int v; double c;
    edge(int v, double c) : v(v), c(c) {}
};

struct node
{
    int v; double c;
    node(int v, double c) : v(v), c(c) {}
    bool operator <(const node& t) const {
	return c > t.c;
    }
};

vector<vector<edge> > E;

int main(){
    while (cin >> n && n) {
	cin >> vw >> vc;
	vw = 1.0 / vw;
	vc = 1.0 / vc;
	rep(i, n)
	    cin >> x[i] >> y[i];

	E.assign(n, vector<edge>());
	rep(i, n - 1)
	    E[i].pb(edge(i + 1, vw * hypot((double) (x[i + 1] - x[i]),
					   (double) (y[i + 1] - y[i]))));

	stack<int> stk;
	rep(i, n - 1) {
	    if (y[i] < y[i + 1])
		stk.push(i);
	    else if (y[i] == y[i + 1]) {
		//
	    } else {
		while (!stk.empty() && y[stk.top()] >= y[i + 1]) {
		    int it = stk.top();
		    stk.pop();
		    if (y[it] == y[i + 1]) {
			E[it].pb(edge(i + 1, vc * (x[i + 1] - x[it])));
			continue;
		    }
		    double p = (double) (y[it] - y[i]) / (y[i + 1] - y[i]);
		    double cx = p * x[i + 1] + (1 - p) * x[i];
		    double cy = p * y[i + 1] + (1 - p) * y[i];

		    int nv = E.size();
		    E.pb(vector<edge>());
		    E[it].pb(edge(nv, vc * (cx - x[it])));
		    E[i].pb(edge(nv, vw * hypot((double) (cx - x[i]),
						(double) (cy - y[i]))));
		    E[nv].pb(edge(i + 1, vw * hypot((double) (cx - x[i + 1]),
						    (double) (cy - y[i + 1]))));
		}
	    }
	}

	stk = stack<int>();
	for (int i = n - 2; i >= 0; --i) {
	    if (y[i] > y[i + 1])
		stk.push(i + 1);
	    else if (y[i] == y[i + 1]) {
		//
	    } else {
		while (!stk.empty() && y[stk.top()] >= y[i]) {
		    int it = stk.top();
		    stk.pop();
		    if (y[it] == y[i]) {
			E[i].pb(edge(it, vc * (x[it] - x[i])));
			continue;
		    }
		    double p = (double) (y[it] - y[i]) / (y[i + 1] - y[i]);
		    double cx = p * x[i + 1] + (1 - p) * x[i];
		    double cy = p * y[i + 1] + (1 - p) * y[i];

		    int nv = E.size();
		    E.pb(vector<edge>());
		    E[nv].pb(edge(it, vc * (x[it] - cx)));
		    E[i].pb(edge(nv, vw * hypot((double) (cx - x[i]),
						(double) (cy - y[i]))));
		    E[nv].pb(edge(i + 1, vw * hypot((double) (cx - x[i + 1]),
						    (double) (cy - y[i + 1]))));
		}
	    }
	}

	fill(mem, mem + N, INF);

	priority_queue<node> q;
	q.push(node(0, 0.0));
	while (!q.empty()) {
	    node tmp = q.top();
	    int v = tmp.v;
	    double c = tmp.c;
	    q.pop();

	    if (v == n - 1) {
		printf("%.6f\n", c);
		break;
	    }
	    if (mem[v] <= c)
		continue;
	    mem[v] = c;

	    rep(i, E[v].size())
		q.push(node(E[v][i].v, c + E[v][i].c));
	}
    }

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1456
final_rank: 5

code_snippet: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
struct Point{
  double x, y;
  Point(){}
  Point(double x, double y) : x(x), y(y) {}
};
struct S{
  int line;
  int height;
  double cost;
  S(int l, int h, int c) :
    line(l), height(h), cost(c) {}
  bool operator < (const S& s) const {
    return cost > s.cost;
  }
};
int lb_index(vector<double>& v, int x){
  return lower_bound(v.begin(), v.end(), x) - v.begin();
}
bool valid_h(S& s, vector<Point>& ps, vector<double>& hs){
  return (s.height >= 0 && s.height < hs.size() && 
          min(ps[s.line].y, ps[s.line + 1].y) <= hs[s.height] &&
          max(ps[s.line].y, ps[s.line + 1].y) >= hs[s.height] );
}
void update(priority_queue<S>& que, double cost[1000][1000], S& next){
  if(cost[next.line][next.height] > next.cost){
    cost[next.line][next.height] = next.cost;
    que.push(next);
  }
}
void print(S& s, vector<double>& hs, vector<Point>& ps){
  printf("line %d: (%.0lf, %.0lf) -> (%.0lf, %.0lf) | height %d: y = %.0lf | cost %lf\n",
      s.line, ps[s.line].x, ps[s.line].y, ps[s.line + 1].x, ps[s.line + 1].y,
      s.height, hs[s.height], s.cost);
}
int main(){
  int N;
  double v_w, v_c;
  while(cin >> N >> v_w >> v_c && N){ 
    vector<Point> ps(N);
    REP(i, N) cin >> ps[i].x >> ps[i].y;
    vector<double> hs(N);
    REP(i, N) hs[i] = ps[i].y;
    sort(hs.begin(), hs.end());
    hs.erase(unique(hs.begin(), hs.end()), hs.end());
    int L = hs.size();
    vector< vector<int> > idxes(L); // y = hs[i]と交わる線分のインデックス
    REP(i, N - 1){
      REP(j, L){
        if(min(ps[i].y, ps[i + 1].y) <= hs[j] && hs[j] <= max(ps[i].y, ps[i + 1].y)){
          idxes[j].push_back(i);
        }
      }
    }
    /*
    REP(i, L){
      printf("idxes[%d]:", i);
      debug(idxes[i].begin(), idxes[i].end());
    }
    */
    priority_queue<S> que;
    double cost[1000][1000] = {};
    REP(i, N) REP(j, L) cost[i][j] = INF;
    cost[0][lb_index(hs, ps[0].y)] = 0;
    que.push(S(0, lb_index(hs, ps[0].y), 0));
    while(!que.empty()){
      S s = que.top(); que.pop();
      //print(s, hs, ps);
      if(cost[s.line][s.height] < s.cost) continue;
      if(s.line == N - 2 && hs[s.height] == ps[s.line + 1].y){
        if(ps[s.line].y == ps[s.line + 1].y) s.cost += (ps[s.line + 1].x - ps[s.line].x) / v_w;
        printf("%.16lf\n", s.cost);
        break;
      }
      if(hs[s.height] == ps[s.line].y){
        if(s.line > 0){
          S next = s;
          next.line --;
          if(ps[next.line].y == ps[next.line + 1].y) next.cost += (ps[next.line + 1].x - ps[next.line].x) / v_w;
          update(que, cost, next);
        }
      }
      if(hs[s.height] == ps[s.line + 1].y){
        if(s.line < N - 2){
          S next = s;
          next.line ++;
          if(ps[s.line].y == ps[s.line + 1].y) next.cost += (ps[s.line + 1].x - ps[s.line].x) / v_w;
          update(que, cost, next);
        }
      }
      for(int d = -1; d <= 1; d += 2){
        S next = s;
        next.height += d;
        if(valid_h(next, ps, hs)){
          assert(ps[s.line + 1].y != ps[s.line].y);
          double C = (ps[s.line + 1].x - ps[s.line].x) / (ps[s.line + 1].y - ps[s.line].y);
          double dy = (hs[s.height + d] - hs[s.height]);
          double dx = C * dy;
          //printf("dx = %lf dy = %lf\n", dx, dy);
          next.cost += sqrt(dx*dx + dy*dy) / v_w; // ??
          update(que, cost, next);
        }
      }
      if(idxes[s.height].back() != s.line && ps[s.line + 1].y != hs[s.height] && ps[s.line].y < ps[s.line + 1].y){
        S next = s;
        next.line = *upper_bound(idxes[s.height].begin(), idxes[s.height].end(), s.line);
        //printf("go tonnnel -> %d\n", next.line);
        double x1 = ps[s.line].x + (ps[s.line + 1].x - ps[s.line].x) * (hs[s.height] - ps[s.line].y) / (ps[s.line + 1].y - ps[s.line].y);
        double x2 = ps[next.line].x +
          ((ps[next.line + 1].y == ps[next.line].y) ? 0 : (ps[next.line + 1].x - ps[next.line].x) * (hs[next.height] - ps[next.line].y) / (ps[next.line + 1].y - ps[next.line].y));
        next.cost += (x2 - x1) / v_c; // ???
        update(que, cost, next);
      }
    }
  }
  return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 10532
final_rank: 14

code_snippet: #include<cmath>
#include<queue>
#include<cstdio>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const double EPS=1e-7;
const double INF=1e77;

struct point{
	double x,y;
	point():x(0),y(0){}
	point(double x,double y):x(x),y(y){}
	point operator+(const point &a)const{ return point(x+a.x,y+a.y); }
	point operator-(const point &a)const{ return point(x-a.x,y-a.y); }
	bool operator< (const point &a)const{ return x+EPS<a.x || abs(x-a.x)<EPS && y+EPS<a.y; }
};

point operator*(double c,const point &a){ return point(c*a.x,c*a.y); }

double dot(const point &a,const point &b){ return a.x*b.x+a.y*b.y; }

double cross(const point &a,const point &b){ return a.x*b.y-a.y*b.x; }

double abs(const point &a){ return sqrt(a.x*a.x+a.y*a.y); }

struct line{
	point a,b;
	line(const point &a,const point &b):a(a),b(b){}
};

struct segment{
	point a,b;
	segment(const point &a,const point &b):a(a),b(b){}
};

bool cover(const segment &S,const point &p){
	return abs(cross(S.a-p,S.b-p))<EPS && dot(S.a-p,S.b-p)<EPS;
}

point get_intersect(const line &L1,const line &L2){
	double a1=cross(L1.b-L1.a,L2.b-L2.a);
	double a2=cross(L1.b-L1.a,L1.b-L2.a);
	if(abs(a1)<EPS) return L1.a;
	return L2.a+a2/a1*(L2.b-L2.a);
}

struct edge{ int v; double cost; };

int main(){
	for(int n;scanf("%d",&n),n;){
		double v1,v2; scanf("%lf%lf",&v1,&v2);
		point p[2000];
		rep(i,n) scanf("%lf%lf",&p[i].x,&p[i].y);

		vector<edge> G[2000];
		int n2=0;
		rep(i,n){
			// dig right
			if(i<n-1 && p[i].y<p[i+1].y){
				int j=i+1;
				while(j<n && p[i].y<p[j].y) j++;
				if(j<n){
					p[n+n2]=get_intersect(line(p[j-1],p[j]),line(p[i],p[i]+point(1,0)));
					G[i].push_back((edge){n+n2,abs(p[i]-p[n+n2])/v2});
					n2++;
				}
			}
			// dig left
			if(i>0 && p[i].y<p[i-1].y){
				int j=i-1;
				while(j>=0 && p[i].y<p[j].y) j--;
				if(j>=0){
					p[n+n2]=get_intersect(line(p[j+1],p[j]),line(p[i],p[i]+point(1,0)));
					G[n+n2].push_back((edge){i,abs(p[i]-p[n+n2])/v2});
					n2++;
				}
			}
		}

		rep(i,n-1){
			vector< pair<point,int> > Q;
			rep(j,n+n2){
				if(cover(segment(p[i],p[i+1]),p[j])) Q.push_back(make_pair(p[j],j));
			}
			sort(Q.begin(),Q.end());
			rep(j,(int)Q.size()-1){
				int u=Q[j].second,v=Q[j+1].second;
				G[u].push_back((edge){v,abs(Q[j+1].first-Q[j].first)/v1});
			}
		}

		double d[2000];
		rep(u,n+n2) d[u]=(u==0?0:INF);

		priority_queue< pair<double,int> > Q;
		Q.push(make_pair(0,0));
		while(!Q.empty()){
			double d_now=-Q.top().first;
			int u=Q.top().second; Q.pop();

			if(d[u]<d_now-EPS) continue;

			rep(i,G[u].size()){
				int v=G[u][i].v;
				double cost=G[u][i].cost;
				if(d[v]>d[u]+cost+EPS){
					d[v]=d[u]+cost;
					Q.push(make_pair(-d[v],v));
				}
			}
		}
		printf("%.9f\n",d[n-1]);
	}

	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 1336
final_rank: 8

code_snippet: #include <cstdio>
#include <iostream>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>

using namespace std;

#define EPS (1e-10)
#define EQ(a,b) (abs((a) - (b)) < EPS)
#define EQV(a,b) (EQ((a).real(),(b).real()) && EQ((a).imag(),(b).imag()))

typedef complex<double> P;
typedef pair<P,P> Edge;
typedef long long ll;

const double PI=4*atan(1.0);
const int MAX_SIZE = 10000;

// 内積
double dot(P a, P b) {
  return (a.real() * b.real() + a.imag() * b.imag());
}
// 外積
double cross(P a, P b) {
  return (a.real() * b.imag() - a.imag() * b.real());
}
// 点cが直線ab上にあるかないか
int is_point_on_line(P a, P b, P c) {
  return EQ( cross(b-a, c-a), 0.0 );
}
// 2直線の直行判定
int is_orthogonal(P a1, P a2, P b1, P b2) {
  return EQ( dot(a1-a2, b1-b2), 0.0 );
}
// 2直線の平行判定
int is_parallel(P a1, P a2, P b1, P b2) {
  return EQ( cross(a1-a2, b1-b2), 0.0 );
}
// 点a,bを通る直線と点cの間の距離
double distance_l_p(P a, P b, P c) {
  return abs(cross(b-a, c-a)) / abs(b-a);
}
// 点a,bを端点とする線分と点cとの距離
double distance_ls_p(P a, P b, P c) {
  if ( dot(b-a, c-a) < EPS ) return abs(c-a);
  if ( dot(a-b, c-b) < EPS ) return abs(c-b);
  return abs(cross(b-a, c-a)) / abs(b-a);
}
// 点が多角形の中に存在するかどうか
bool isInPolygon(vector<P> &points,P s){
	if(points.size()==1)return false;
	vector<P> v;
	for(int i=0;i<(int)points.size();i++)v.push_back(points[i]-s);
	int sign=0;
	for(int i=1;i<=(int)v.size();i++){
		int prv=(i-1+v.size())%v.size();
		int cur=i%v.size();
		double c=cross(v[prv],v[cur]);
		if(EQ(c,0))continue;
		else if(sign==0){
			if(c>0)sign=1;
			else sign=-1;
		}
		else{
			if(sign==-1&&c>0)return false;
			else if(sign==1&&c<0)return false;
		}
	}
	return true;
}
struct Rec{
	vector<P> p;
};
// a1,a2を端点とする線分とb1,b2を端点とする線分の交差判定
int is_intersected_ls(P a1, P a2, P b1, P b2) {
    // 線分が平行な場合は重なっていないことにする
    if(abs(cross(a2-a1,b2-b1)) < EPS){
      return 0;
    }
    return ( cross(a2-a1, b1-a1) * cross(a2-a1, b2-a1) < EPS ) &&
        ( cross(b2-b1, a1-b1) * cross(b2-b1, a2-b1) < EPS );
}
// aとbの矩形が接しているかどうか(どちらかがどちからを含んでいるものもふくむ
bool isTouchRectangle(Rec &a,Rec &b){
  // aの各頂点がbの中に存在しているかチェック
  for(int i=0;i<4;i++)if(isInPolygon(b.p,a.p[i]))return true;
  // 逆
  for(int i=0;i<4;i++)if(isInPolygon(a.p,b.p[i]))return true;
  // 各辺が他方のどれかの辺と接しているか
  for(int i=0;i<4;i++){
    int curi=i;
    int prvi=(i-1+4)%4;
    for(int j=0;j<4;j++){
      int curj=j;
      int prvj=(j-1+4)%4;
      if(is_intersected_ls(a.p[curi],a.p[prvi],b.p[curj],b.p[prvj]))return true;
    }
  }
  return false;
}
// a1,a2を端点とする線分とb1,b2を端点とする線分の交点計算
P intersection_ls(P a1, P a2, P b1, P b2) {
  P b = b2-b1;
  double d1 = abs(cross(b, a1-b1));
  double d2 = abs(cross(b, a2-b1));
  double t = d1 / (d1 + d2);
  return a1 + (a2-a1) * t;
}
// a1,a2を通る直線とb1,b2を通る直線の交差判定
int is_intersected_l(P a1, P a2, P b1, P b2) {
  return !EQ( cross(a1-a2, b1-b2), 0.0 );
}
// a1,a2を通る直線とb1,b2を通る直線の交点計算
P intersection_l(P a1, P a2, P b1, P b2) {
  P a = a2 - a1; P b = b2 - b1;
  return a1 + a * cross(b, b1-a1) / cross(b, a);
}
// 単位ベクトルを求める
P normalVector(P p){
	return p/abs(p);
}
// 法線ベクトルを求める
P unitVector(P a){
	return P(-a.imag(),a.real());
}
// 単位法線ベクトルを求める
P unitNormalVector(P tmp){
	P e=P(-tmp.imag(),tmp.real());
	e/=abs(e);
	return e;
}
// 座標の回転(座標pにある点を,半時計回りにa(ラジアン)回転)
P roundPoint(P p,double a){
	return P(cos(a)*p.real()-sin(a)*p.imag(),sin(a)*p.real()+cos(a)*p.imag());
}
/*
円周と線分の交差判定
*/
bool isCircleCrossLine(P a,P b,P c,double r){
	double d1 = abs(a-c);
	double d2 = abs(b-c);
    // 線分が中に含まれるとき、ここのコメントアウトをはずせばtrue(交差)となる
	//if(d1<r&&d2<r)
	//	return true;
	double d = distance_ls_p(a,b,c);
	return (EQ(d,r)||d<r);
}
// 三角形の内部に点があるかどうか
// 外積の正負がすべて同じなら内部に点あり
bool isInTriangle(P p1,P p2,P p3,P s){
	P a=p1-s;
	P b=p2-s;
	P c=p3-s;
	return ((cross(a,b)>0&&cross(b,c)>0&&cross(c,a)>0)||(cross(a,b)<0&&cross(b,c)<0&&cross(c,a)<0));
}
// 矩形の中に点が存在するかどうか
bool isInRectangle(P p1,P p2,P p3,P p4,P s){
	P a=p1-s;
	P b=p2-s;
	P c=p3-s;
    P d=p4-s;
	return ((cross(a,b)>0&&cross(b,c)>0&&cross(c,d)>0&&cross(d,a)>0)
        ||(cross(a,b)<0&&cross(b,c)<0&&cross(c,d)<0&&cross(d,a)<0));
}
// 三角形の面積を座標から計算
double calcAreaOfTriangle(P a,P b,P c){
	return abs((b.real()-a.real())*(c.imag()-a.imag()) - (c.real()-a.real())*(b.imag()-a.imag()))/2;
}
// 与えられた円の範囲内に点が存在するかどうか
bool isContainingDot(P c,double r,P a){
	return (((c.real()-a.real())*(c.real()-a.real())
		+(c.imag()-a.imag())*(c.imag()-a.imag())<r*r)
		||EQ((c.real()-a.real())*(c.real()-a.real())
		+(c.imag()-a.imag())*(c.imag()-a.imag()),r*r));
}
// 多角形の面積公式
double calcPolygonArea(vector<P> p){
	double sum=0;
	for(int i = 0; i < p.size(); i++)
		sum+=cross(p[i],p[(i+1)%(p.size())]);
	return abs(sum/2);
}
// 2ベクトル間の角度
// aからbへ左周りで何度か(0->2*PI)
double diffAngle(P a,P b){
    double angle=atan2(cross(a,b),dot(a,b));
    if(angle<0)
        return 2*PI+angle;
    return angle;
}
// 2つのベクトルの重なっている部分の長さを返す
// もし重なっていなければ0を返す
double multipleLength(P a,P b,P c,P d){
    Edge e1=make_pair(a,b);
    Edge e2=make_pair(c,d);
    // 平行であるかどうか
    if(!(is_parallel(e1.first,e2.first,e1.second,e2.second)
        &&is_parallel(e1.first,e1.second,e2.first,e2.second)))
        return 0;
    double dist=0;
    // 両方乗っている
    if(EQ(distance_ls_p(e1.first,e1.second,e2.first),0)&&EQ(distance_ls_p(e1.first,e1.second,e2.second),0))
        dist=abs(e2.first-e2.second);
    else if(EQ(distance_ls_p(e2.first,e2.second,e1.first),0)&&EQ(distance_ls_p(e2.first,e2.second,e1.second),0))
        dist=abs(e1.first-e1.second);
    else if(EQ(distance_ls_p(e1.first,e1.second,e2.first),0)){
        // どちらが線上にあるか
        if(EQ(distance_ls_p(e2.first,e2.second,e1.first),0))
            dist=abs(e1.first-e2.first);
        else
            dist=abs(e1.second-e2.first);
    }
    else if(EQ(distance_ls_p(e1.first,e1.second,e2.second),0)){
        if(EQ(distance_ls_p(e2.first,e2.second,e1.first),0))
            dist=abs(e1.first-e2.second);
        else
            dist=abs(e1.second-e2.second);
    }
    return dist;
}
// 2点を通る半径rの円の中点を求める
pair<P,P> calcCircleCenterPoint(P dot1,P dot2,double r){
    double v=abs(dot1-dot2);
    double x = sqrt(r*r - (v/2)*(v/2));
    // 二組の単位法線ベクトル
    P hose[2];
    double x1=-(dot1.imag()-dot2.imag());
    double y1=(dot1.real() - dot2.real());
    hose[0]=P(x1,y1);
    double y2=-y1;
    double x2=-x1;
    hose[1]=P(x2,y2);
    double dd1=abs(hose[0]);
    double dd2=abs(hose[1]);
    hose[0]/=dd1;hose[0]*=x;
    hose[1]/=dd2;hose[1]*=x;
    P tmp=(dot1+dot2);
    tmp/=2;
    hose[0]+=tmp;
    hose[1]+=tmp;
    return make_pair(hose[0],hose[1]);
}
// 4線分が端点以外でクロスしているかどうかを判定
bool checkCross(const vector<Edge> &vec){
    for(int i=0;i<vec.size();i++){
        for(int j=i+1;j<vec.size();j++){
            // 線分がクロスしているかどうか
            if(is_intersected_ls(vec[i].first,vec[i].second,vec[j].first,vec[j].second)){
                // している場合、端点以外でクロスしているなら、false
                P p=intersection_ls(vec[i].first,vec[i].second,vec[j].first,vec[j].second);
                if(!(EQ(p,vec[i].first)||EQ(p,vec[i].second)))
                    return false;
            }
        }
    }
    return true;
}
// 引き数で与えられた4つの点が矩形を作るどうかを判定
bool checkRec(const vector<P> &squ){
    vector<int> v;
    for(int i=0;i<squ.size();i++)v.push_back(i);
    do{
        vector<Edge> ve;
        for(int i=0;i<4;i++)
            ve.push_back(make_pair(squ[v[i]],squ[v[(i+1)%4]]));
        // ここですべての線分がクロスするかどうかを計算
        if(checkCross(ve)){
            // 線分の長さを確認
            if(EQ(abs(ve[0].first-ve[0].second),abs(ve[2].first-ve[2].second)))
                if(EQ(abs(ve[1].first-ve[1].second),abs(ve[3].first-ve[3].second)))
                    // 直行
                    if(is_orthogonal(ve[0].first,ve[0].second,ve[1].first,ve[1].second))
                        if(is_orthogonal(ve[2].first,ve[2].second,ve[3].first,ve[3].second))
                        return true;
        }
    }while(next_permutation(v.begin(),v.end()));
    return false;
}
// 引き数で与えられた4つの点が正方形を作るかどうかを判定
bool checkSqu(const vector<P> &squ){
    vector<int> v;
    for(int i=0;i<squ.size();i++)v.push_back(i);
    do{
        vector<Edge> ve;
        for(int i=0;i<4;i++)
            ve.push_back(make_pair(squ[v[i]],squ[v[(i+1)%4]]));
        // ここですべての線分がクロスするかどうかを計算
        if(checkCross(ve)){
            // 線分の長さを確認
            double d=abs(ve[0].first-ve[0].second);
            for(int i=1;i<4;i++){
                double d2=abs(ve[i].first-ve[i].second);
                if(!EQ(d,d2))return false;
            }
            // 直行確認
            if(is_orthogonal(ve[0].first,ve[0].second,ve[1].first,ve[1].second))
                if(is_orthogonal(ve[2].first,ve[2].second,ve[3].first,ve[3].second))
                    return true;
        }
    }while(next_permutation(v.begin(),v.end()));
    return false;
}
// 二円の共通接線を構成する4直線を求める(二円はお互い接したりどちらかをふくんだりしない)
vector<pair<P,P> > calcCommonTangentialLine(P p1,double r1,P p2,double r2){
	vector<pair<P,P> > res;
	if(r1>r2){
		swap(r1,r2);
		swap(p1,p2);
	}
	// 共通外接線
	{
		double d=abs(p1-p2);
		double a=abs(r1-r2);
		double b=sqrt(d*d-a*a);
		double sita=acos(b/d);
		P e=normalVector(roundPoint((roundPoint((p2-p1),sita)),PI/2));
		res.push_back(make_pair(e*r1+p1,e*r2+p2));
		P e2=normalVector(roundPoint((roundPoint((p2-p1),-sita)),-PI/2));
		res.push_back(make_pair(e2*r1+p1,e2*r2+p2));
	}
	// 共通内接線
	{
		P cp=(r1*p1+r2*p2)/(r1+r2);
		double u=abs(cp-p1);
		double sita=acos(r1/u);
		P e=normalVector(roundPoint(cp-p1,sita));
		res.push_back(make_pair(e*r1+p1,-e*r2+p2));
		P e2=normalVector(roundPoint(cp-p1,-sita));
		res.push_back(make_pair(e2*r1+p1,-e2*r2+p2));
	}
	return res;
}
/*
  与えられた3点a,b,c,をa->b->cと進むとき
  a->bで時計方向に折れて,b->c
  a->bで半時計方向に折れて,b->c
  a->bで逆を向いてaを通り越してb->c
  a->bでそのままb->c
  a->bで逆を向いてb->c
  のどれであるかを判定
*/
int ccw(P a,P b, P c){
  b-=a;c-=a;
  if(cross(b,c)>0&&!EQ(cross(b,c),0))return 1;// counter clockwise
  if(cross(b,c)<0&&!EQ(cross(b,c),0))return -1;// clockwise
  if(dot(b,c)<0&&!EQ(dot(b,c),0))return 2; // c-a-b on line
  if(!EQ(abs(b),abs(c))&&abs(b)<abs(c))return -2; // a-b-c on line
  return 0;
}
// 凸多角形の切断を行う
// lineのfirst側から見て右の多角形が返る
// 多角形は上が+y,右が+xの座標系で座標を時計周りに格納したvectorで表す
// lineは基本的にmakeDivisorで作成
vector<P> convex_cut(vector<P> polygon,pair<P,P> line){
  vector<P> resPolygon;
  int n=polygon.size();
  for(int i=0;i<n;i++){
    P A=polygon[i];
    P B=polygon[(i+1)%n];
    if(ccw(line.first,line.second,A)!=-1)
      resPolygon.push_back(A);
    if(ccw(line.first,line.second,A)*ccw(line.first,line.second,B)<0)
      resPolygon.push_back(intersection_l(A,B,line.first,line.second));
  }
  return resPolygon;
}

struct Point{
  P p;
  Point(P _p){
    p=_p;
  }
  Point(){}
  bool operator<(const Point &op)const{
    if(EQ(p.real(),op.p.real())){
      if(EQ(p.imag(),op.p.imag()))return false;
      else return p.imag()<op.p.imag();
    }
    return p.real()<op.p.real();
  }
};
struct edge{
  double dist;
  Point to;
};

const int MAX_N=10000;
const int INF=1000000000;
vector<edge> G[MAX_N];
double d[MAX_N];
vector<P> ps;
set<Point> nodes;
map<Point,int> m;
int idx;
int n;

typedef pair<double,int> pii;

double dijkstra(){
  for(int i=0;i<idx;i++)d[i]=INF;
  priority_queue<pii> pq;
  pq.push(pii(0,m[Point(ps[0])]));
  // start
  d[m[Point(ps[0])]]=0;
  while(pq.size()){
    pii p=pq.top();pq.pop();
    double cost=p.first;
    int node=p.second;
    if(!EQ(d[node],cost)&&d[node]<cost)continue;
    for(int i=0;i<G[node].size();i++){
      edge &e=G[node][i];
      if(!EQ(d[m[e.to]],cost+e.dist)&&d[m[e.to]]>cost+e.dist){
	d[m[e.to]]=cost+e.dist;
	pq.push(pii(d[m[e.to]],m[e.to]));
      }
    }
  }
  // ゴールへの最短距離
  return d[m[Point(ps[n-1])]];
}

int main(){
  while(cin>>n&&n){
    double vw,vc;
    idx=0;ps.clear();m.clear();nodes.clear();
    cin>>vw>>vc;
    for(int i=0;i<n;i++){
      double x,y;
      cin>>x>>y;
      ps.push_back(P(x,y));
    }
    for(int i=0;i<n;i++){
      if(m.count(Point(ps[i]))==0){
	nodes.insert(Point(ps[i]));
	m[Point(ps[i])]=idx++;
      }
      // 谷の端点の場合、左右に伸ばす
      // 右　
      if((i+1<n&&!EQ(ps[i+1].imag(),ps[i].imag())&&(ps[i+1].imag()>ps[i].imag()))){
	for(int j=i+1;j<n-1;j++){
	  P a=ps[j];
	  P b=ps[j+1];
	  // 線分a--bとy=ps[i].imag()が交差するか？
	  // 交差するなら,nodeを追加
	  if(is_intersected_ls(a,b,P(-1000000,ps[i].imag()),P(1000000,ps[i].imag()))){
	    P cp=intersection_ls(a,b,P(-1000000,ps[i].imag()),P(1000000,ps[i].imag()));
	    if(m.count(Point(cp))==0){
	      m[Point(cp)]=idx++;
	      nodes.insert(Point(cp));
	    }
	    break;
	  }
	  // 平行かつy座標が同じ線分にぶつかった場合
	  else if(EQ(ps[i].imag(),ps[j].imag())&&EQ(ps[j].imag(),ps[j+1].imag()))break;
	}
      }
      // 左
      if(i-1>=0&&!EQ(ps[i-1].imag(),ps[i].imag())&&(ps[i-1].imag()>ps[i].imag())){
	for(int j=i-1;j>0;j--){
	  P a=ps[j];
	  P b=ps[j-1];
	  // 線分a--bとy=ps[i].imag()が交差するか？
	  // 交差するなら,nodeを追加
	  if(is_intersected_ls(a,b,P(-1000000,ps[i].imag()),P(1000000,ps[i].imag()))){
	    P cp=intersection_ls(a,b,P(-1000000,ps[i].imag()),P(1000000,ps[i].imag()));
	    if(m.count(Point(cp))==0){
	      nodes.insert(Point(cp));
	      m[Point(cp)]=idx++;
	    }
	    break;
	  }
	  else if(EQ(ps[i].imag(),ps[j].imag())&&EQ(ps[j].imag(),ps[j-1].imag()))break;
	}
      }
    }
    // 交点の位置でソートしておき
    // 一つ隣の交点は通行可能
    // その他同じy座標を持つところにも通行可能
    for(set<Point>::iterator it=nodes.begin();it!=nodes.end();it++){
      //cout<<it->p<<endl;
      // 歩いていけるところにエッジを結ぶ
      set<Point>::iterator nxt=it;nxt++;
      if(nxt!=nodes.end()){
	edge e;
	// 隣接地点へ歩いて渡る
	e.dist=abs((it->p)-(nxt->p))/vw;
	e.to=*it;G[m[*nxt]].push_back(e);
	e.to=*nxt;G[m[*it]].push_back(e);
      }
      // 同じy座標のノードを追加
      // x座標で隣接するものを使用
      int ang=-1;
      for(set<Point>::iterator iit=it;iit!=nodes.end();iit++){
	// 最初は一つ進めておく
	if(iit==it)iit++;
	if(iit==nodes.end())break;
	if(EQ(iit->p.imag(),it->p.imag())){
	  set<Point>::iterator itnxt=it;itnxt++;
	  // 隣は歩いていけるのでx
	  if(itnxt!=iit){
	    if(ang==0)continue;
	    edge e;
	    e.dist=abs((iit->p)-(it->p))/vc;
	    e.to=*iit;
	    G[m[*it]].push_back(e);
	  }
	  break;
	}
	if(ang==-1){
	  if(iit->p.imag()>it->p.imag())ang=1;//zouka
	  else ang=0;//heru
	}
      }
      // ang=-1;
      // for(set<Point>::iterator iit=it;;iit--){
      //  	if(iit==nodes.begin())break;
      // 	// 最初は一つ進めておく
      // 	if(iit==it)iit--;
      // 	// y座標が一致
      // 	if(EQ(iit->p.imag(),it->p.imag())){
      // 	  set<Point>::iterator itnxt=it;itnxt--;
      // 	  // 隣は歩いていけるのでx
      // 	  if(itnxt!=iit){
      // 	    if(ang==0)continue;
      // 	    edge e;
      // 	    e.dist=abs((iit->p)-(it->p))/vc;
      // 	    e.to=*iit;
      // 	    G[m[*it]].push_back(e);
      // 	  }
      // 	  break;
      // 	}
      // 	if(ang==-1){
      // 	  if(iit->p.imag()>it->p.imag())ang=0;//zouka
      // 	  else ang=1;//heru
      // 	}
      // 	if(iit==nodes.begin())break;
      // }
    }
    double res=dijkstra();
    printf("%.10f\n",res);
    for(int i=0;i<idx;i++)G[i].clear();
  }

  return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 0
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;

int main(){
	int n;
	int x[1000], y[1000];
	double xd[3000], yd[3000], dist[3000];
	int next[3000];
	while(cin >> n, n){
		int vw, vc; cin >> vw >> vc;
		for(int i=0;i<n;i++){
			cin >> x[i] >> y[i];
			xd[i] = x[i];
			yd[i] = y[i];
			next[i] = -1;
		}
		int size = n;
		for(int i=0;i<n;i++){
			if(i+1 < n && y[i] < y[i+1]){
				for(int j=i+1;j+1<n;j++){
					if(y[j+1] == y[i]){
						next[i] = j+1;
						break;
					}
					if(min(y[j], y[j+1]) <= y[i] && y[i] <= max(y[j], y[j+1])){
						xd[size] = (y[i]-yd[j])*(xd[j+1]-xd[j])/(yd[j+1]-yd[j]) + xd[j];
						yd[size] = y[i];
						next[i] = size;
						next[size] = -1;
						size++;
						break;
					}
				}
			}
			if(i-1 >= 0 && y[i] < y[i-1]){
				for(int j=i-1;j-1>=0;j--){
					if(y[j-1] == y[i]){
						next[j-1] = i;
						break;
					}
					if(min(y[j], y[j-1]) <= y[i] && y[i] <= max(y[j], y[j-1])){
						xd[size] = (y[i]-yd[j])*(xd[j-1]-xd[j])/(yd[j-1]-yd[j]) + xd[j];
						yd[size] = y[i];
						next[size] = i;
						size++;
						break;
					}
				}
			}
		}
		vector< pair<double, int> > vp;
		for(int i=0;i<size;i++){
			dist[i] = 1e12;
			vp.push_back(make_pair(xd[i], i));
		}
		sort(vp.begin(), vp.end());
		dist[0] = 0;
		for(int i=0;i+1<vp.size();i++){
			int pos  = vp[i].second;
			int npos = vp[i+1].second;
			dist[npos] = min(dist[npos], dist[pos] + hypot(xd[pos]-xd[npos], yd[pos]-yd[npos])/vw);
			if(next[pos] != -1)
				dist[next[pos]] = min(dist[next[pos]], dist[pos] + (xd[next[pos]] - xd[pos])/vc);
		}
		printf("%.8lf\n", dist[n-1]);
	}
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1

code_snippet: #include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <climits>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1<<29;
const double PI = acos(-1);
const double EPS = 1e-8;
typedef complex<double> P;
namespace std {
  bool operator < (const P& a, const P& b) {
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
};
int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > 0)   return +1;       // counter clockwise
  if (cross(b, c) < 0)   return -1;       // clockwise
  if (dot(b, c) < 0)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}
bool intersectLS(const L &l, const L &s) {
  return cross(l[1]-l[0], s[0]-l[0])*       // s[0] is left of l
         cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l
}
P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}
double dp[1001];
P p[1001];
int main() {
  int n;
  while(cin >> n, n) {
    int vw, vc;
    cin >> vw >> vc;
    REP(i, n) {
      int x, y;
      cin >> x >> y;
      p[i] = P(x,y);
    }
    REP(i, n) dp[i] = INF;
    dp[0] = 0;
    REP(i, n-1) {
      //cout << dp[i] << " ";
      dp[i+1] = min(dp[i+1], dp[i] + abs(p[i] - p[i+1]) / vw);
      if (p[i+1].imag() > p[i].imag()) {
        int mi = p[i+1].imag();
        for (int j=i+2; j<n; ++j) {
          if (mi > p[j].imag()) {
            mi = p[j].imag();
            if (mi < p[i].imag()) {
              P q = crosspoint(L(p[i], p[i]+P(1,0)), L(p[j-1], p[j]));
              dp[j] = min(dp[j], dp[i] + (q.real()-p[i].real()) / vc + abs(p[j]-q) / vw);
              break;
            } else {
              P q = crosspoint(L(p[i], p[i+1]), L(p[j], p[j]+P(1,0)));
              dp[j] = min(dp[j], dp[i] + abs(p[i]-q) / vw + (p[j].real()-q.real()) / vc);
            }
          }
        }
      }
    }
    printf("%.8f\n", dp[n-1]);
  }
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
#include <complex>
#include <utility>
#include <cstdio>
#include <cassert>
#include <algorithm>

using namespace std;

typedef complex<double> Vector;
typedef pair<Vector,Vector> Line;

const double EPS = 1e-7;

namespace std {
    bool operator < (const Vector &a, const Vector &b) {
        return a.real() < b.real();
    }
};

inline bool eqv(double a, double b) {
    return fabs(a-b) < EPS;
}

struct Comp {
    vector<Vector> vs;
    Comp(const vector<Vector> &vs) : vs(vs) {}

    bool operator ()(const int a, const int b) const {
        if(eqv(vs[a].real(), vs[b].real())) return a < b;
        return vs[a] < vs[b];
    }
};


//Verified PKU 2812
double cross(const Vector &v1, const Vector &v2) {
    return (v1.real()*v2.imag()) - (v1.imag()*v2.real());
}

bool intersect(const Vector &p11, const Vector &p12, const Vector &p21, const Vector &p22) {
    return (cross(p12-p11, p21-p11)*cross(p12-p11, p22-p11) < 0 &&
            cross(p22-p21, p11-p21)*cross(p22-p21, p12-p21) < 0 );
}

//Verified AOJ 0012
//Verified PKU 3348
double ccw(const Vector &p1, const Vector &p2, const Vector &p3) {
    return cross(p2-p1, p3-p1);
}

//Verified AOJ 1267(maybe too weak)
Vector crosspoint(const Line &l1, const Line &l2) {
    double a = cross(l1.second-l1.first, l2.second-l2.first);
    double b = cross(l1.second-l1.first, l1.second-l2.first);
    if(fabs(a) < EPS && fabs(b) < EPS) return l2.first;
    assert(fabs(a) >= EPS);
    return l2.first + b / a * (l2.second-l2.first);
}

int main() {
    while(true) {
        int N;
        cin >> N;
        if(!N) break;

        int VW, VC;
        cin >> VW >> VC;

        vector<Vector> vs(N);
        vector<vector<double> > cost(N*3, vector<double>(N*3, 1e12));
        for(int i = 0; i < N; ++i) {
            cin >> vs[i].real() >> vs[i].imag();
        }

        for(int i = N-1; i >= 0; --i) {
            //Search Right
            double y = vs[i].imag();
            if(i+1 < N && vs[i+1].imag() > y) {
                for(int j = i+1; j < N; ++j) {
                    if(vs[j].imag() < y || eqv(vs[j].imag(), y)) {
                        //intersect with line (vs[j], vs[j-1])
                        //cout << "intersect " << vs[i] << ' '  << vs[j] << endl;
                        Vector pt = crosspoint(Line(vs[j], vs[j-1]+(vs[j-1]-vs[j])), Line(vs[i], Vector(vs[j].real()+10, y)));
                        vs.push_back(pt);
                        int idx = (int)vs.size()-1;
                        cost[idx][i] = (pt.real() - vs[i].real()) / VC;
                        break;
                    }
                }
            }

            //Search Left
            if(i-1 >= 0 && vs[i-1].imag() > y) {
                for(int j = i-1; j >= 0; --j) {
                    if(vs[j].imag() < y || eqv(vs[j].imag(), y)) {
                        //intersect with line (vs[j+1], vs[j])
                        Vector pt = crosspoint(Line(vs[j+1], vs[j]+(vs[j]-vs[j+1])), Line(vs[i], Vector(vs[j].real()-10, y)));
                        vs.push_back(pt);
                        int idx = (int)vs.size()-1;
                        cost[i][idx] = (vs[i].real() - pt.real()) / VC;
                        break;
                    }
                }
            }
        }

        vector<int> order(vs.size());
        for(int i = 0; i < order.size(); ++i) order[i] = i;
        sort(order.begin(), order.end(), Comp(vs));

        vector<double> best(vs.size(), 1e12);
        best[order[vs.size()-1]] = 0;
        for(int i = (int)vs.size()-1; i >= 1; --i) {
            int cur = order[i];
            int next = order[i-1];
            cost[cur][next] = abs(vs[next]-vs[cur]) / VW;

            for(int j = 0; j < i; ++j) {
                int nx = order[j];
                assert(cost[cur][nx] >= 0);
                best[nx] = min(best[nx], best[cur] + cost[cur][nx]);
            }
            //cout << best[cur] << endl;
        }

        printf("%.7f\n", best[order[0]]);
    }

    return 0;
}
accuracy: 1
time_ms: 620
memory_kb: 0
final_rank: 12

code_snippet: #include <cstdio>
#include <vector>
#include <queue>
#include <complex>
using namespace std;
typedef complex<double> P;
static const double EPS = 1e-6;
inline double cross(const P& a, const P& b) { return a.real()*b.imag() - b.real()*a.imag(); }

struct line/*{{{*/
{
  P a, b;
  line() {}
  line(const P& p, const P& q) : a(p), b(q) {}
};/*}}}*/

struct segment/*{{{*/
{
  P a, b;
  segment() {}
  segment(const P& x, const P& y) : a(x), b(y) {}

  inline bool intersects(const line& ln) const
  {
    return cross(ln.b - ln.a, a - ln.a) * cross(ln.b - ln.a, b - ln.a) < EPS;
  }

  inline P intersection(const line& ln) const
  {
    const P x = b - a;
    const P y = ln.b - ln.a;
    return a + x*(cross(y, ln.a - a))/cross(y, x);
  }
};/*}}}*/

int main()
{
  int N;
  while (scanf("%d", &N) != EOF && N != 0) {
    int vw, vc;
    scanf("%d %d", &vw, &vc);
    vector<P> ps;
    for (int i = 0; i < N; i++) {
      int x, y;
      scanf("%d %d", &x, &y);
      ps.push_back(P(x, y));
    }

    vector<vector<pair<int,double> > > g(3*N);
    for (int i = 0; i < N-1; i++) {
      g[3*i].push_back(make_pair(3*(i+1), abs(ps[i+1] - ps[i])/vw));
    }
    for (int i = 0; i < N; i++) {
      if (i > 0 && ps[i-1].imag() > ps[i].imag()) {
        // left edge
        const line ln(ps[i], ps[i] + P(1, 0));
        for (int j = i-2; j >= 0; j--) {
          const segment s(ps[j], ps[j+1]);
          if (s.intersects(ln)) {
            const P p = s.intersection(ln);
            const int n = 3*i+1;
            g[3*j].push_back(make_pair(n, abs(p - ps[j])/vw));
            g[n].push_back(make_pair(3*i, abs(ps[i] - p)/vc));
            break;
          }
        }
      }
      if (i < N-1 && ps[i].imag() < ps[i+1].imag()) {
        // right edge
        const line ln(ps[i], ps[i] + P(1, 0));
        for (int j = i+1; j < N-1; j++) {
          const segment s(ps[j], ps[j+1]);
          if (s.intersects(ln)) {
            const P p = s.intersection(ln);
            const int n = 3*i+2;
            g[3*i].push_back(make_pair(n, abs(p - ps[i])/vc));
            g[n].push_back(make_pair(3*(j+1), abs(ps[j+1] - p)/vw));
            break;
          }
        }
      }
    }

    static const double INF = 1e10;
    vector<double> dist(3*N, INF);
    dist[0] = 0;
    priority_queue<pair<double,int> > q;
    q.push(make_pair(0, 0));
    while (!q.empty()) {
      const double c = -q.top().first;
      const int n = q.top().second;
      q.pop();
      if (n == 3*(N-1)) {
        printf("%.6f\n", c);
        break;
      }
      if (c > dist[n]) {
        continue;
      }
      for (vector<pair<int,double> >::const_iterator it = g[n].begin(); it != g[n].end(); ++it) {
        const int m = it->first;
        const double cc = c + it->second;
        if (cc < dist[m]) {
          dist[m] = cc;
          q.push(make_pair(-cc, m));
        }
      }
    }
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1

code_snippet: #include <iostream>
#include <complex>
#include <vector>
#include <iomanip>
#include <queue>
using namespace std;

typedef complex<double> P;
#define EPS 1e-5
#define INF 1e7

typedef pair<int, double> Node;

class State
{
public:
	int n;
	double c;
	State(int n, double c)
		:n(n),c(c)
	{}

	bool operator<(const State& s) const
	{
		return c>s.c;
	}
};

//üª
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
};


//OÏ
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}

double dist(const P& a, const P& b)
{
	return abs(a-b);
}

bool intersect(L& a, L& b)
{
	double t=max(a[0].imag(), a[1].imag());
	double l=min(a[0].imag(), a[1].imag());

	return (t+EPS>b[0].imag()&&b[0].imag()>l-EPS);
}

P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  return m[0] + B / A * (m[1] - m[0]);
}

int main()
{
	cout << setprecision(10) << setiosflags(ios::fixed);
	double vw,vc;
	int N;
	
	while(cin >> N, N)
	{
		vector<P> in;

		cin >> vw >> vc;
		for(int i=0; i<N; i++)
		{
			double x,y;
			cin >> x >> y;
			in.push_back(P(x,y));
		}

		vector<Node> node[4000];
		for(int i=0; i<N-1; i++)
		{
			node[i].push_back(make_pair(i+1, dist(in[i], in[i+1])/vw));
		}

		for(int i=0; i<N; i++)
		{
			L hz(P(-INF,in[i].imag()),P(INF,in[i].imag()));
			for(int j=i-2; j>=0; j--)
			{
				if(in[i].imag()+EPS > in[j+1].imag()) break;
				L tmp(in[j], in[j+1]);
				if(intersect(tmp,hz))
				{
					P xp=crosspoint(hz,tmp);
					in.push_back(xp);
					int p=in.size();
					node[j].push_back(make_pair(p, dist(in[j], xp)/vw));
					node[p].push_back(make_pair(j+1, dist(in[j+1], xp)/vw));
					node[p].push_back(make_pair(i, dist(in[i], xp)/vc));
					
					break;
				}
			}
			for(int j=i+1; j<N-1; j++)
			{
				if(in[i].imag()+EPS > in[j].imag()) break;

				L tmp(in[j], in[j+1]);
				if(intersect(tmp,hz))
				{
					P xp=crosspoint(hz,tmp);
					in.push_back(xp);
					int p=in.size();
					node[j].push_back(make_pair(p, dist(in[j], xp)/vw));
					node[p].push_back(make_pair(j+1, dist(in[j+1], xp)/vw));
					node[i].push_back(make_pair(p, dist(in[i], xp)/vc));
					
					break;
				}
			}
		}

		priority_queue<State> q;
		q.push(State(0,0));
		bool v[4000]={0};

		while(!q.empty())
		{
			State s=q.top(); q.pop();
			if(v[s.n]) continue;
			v[s.n]=1;

			if(s.n==N-1)
			{
				cout << s.c << endl;
				break;
			}

			for(int i=0; i<node[s.n].size(); i++)
			{
				Node next=node[s.n][i];
				if(v[next.first]) continue;

				q.push(State(next.first, s.c+next.second));
			}

		}


	}
}
accuracy: 1
time_ms: 90
memory_kb: 1188
final_rank: 9

code_snippet: #include<iostream>
#include<cmath>
#include<complex>
#include<queue>
#include<functional>
#include<algorithm>
#include<set>

using namespace std;

typedef double elem;
typedef complex<elem> point, vec;
typedef pair<point,point> line;

#define N 1001

const elem eps = 1.0e-7;
const elem infty = 300000000.0;

elem W[N][N];
elem A[N];
bool G[N][N];

struct State{
  int now;
  elem cost;
  bool operator>(const State&t)const{
    return cost > t.cost;
  }
};

elem cross(point a, point b){
  return a.real() * b.imag() - a.imag() * b.real();
}

elem dist(point a, point b){
  return abs(b-a);
}
elem dist(point a1, point a2, point x){
  return abs( cross(a2-a1,x-a1)) / abs(a2-a1);
}

inline bool intersected_seg(point a1, point a2, point b1, point b2){
  return (cross(a2-a1,b1-a1)*cross(a2-a1,b2-a1) < eps &&
	  cross(b2-b1,a1-b1)*cross(b2-b1,a2-b1) < eps );
}

inline point intersection_seg(point a1, point a2, point b1, point b2){
  elem d1=dist(b1,b2,a1);
  elem d2=dist(b1,b2,a2);
  elem t=d1/(d1+d2);
  return a1+t*(a2-a1);
}

void ResetGraph(){
  for(int i = 0; i < N; ++i){
    A[i] = infty;
    for(int j = 0; j < N; ++j){
      W[i][j] = infty;
      G[i][j] = false;
    }
  }
}

elem dijkstra(int goal){
  priority_queue< State, vector<State>, greater<State> > pq;
  bool visited[N]={false,};
  State st;

  st.now = 0;
  visited[0] = true;
  st.cost = 0;
  A[0] = 0;
  pq.push( st );

  while( !pq.empty() ){
    st = pq.top();
    //cout << " QUEUE SIZE "  << pq.size() << endl;
    pq.pop();

    //cout << "NOW: " << st.now << " COST : " << st.cost << endl;

    //visited[st.now] = false;
    if( st.now == goal ){
      return A[goal];
    }
    visited[st.now] = true;

    for(int i = 0; i < N; ++i){
      if( G[st.now][i] ){
	if( !visited[i] && A[st.now] + W[st.now][i] < A[i] ){
	  State next;
	  next.now = i;
	  A[i] = A[st.now] + W[st.now][i];
	  //cout << "Goto : " << i << endl;
	  //cout << "Right : " << A[st.now] << " + " <<  W[st.now][i] << endl;
	  next.cost = A[i];
	  pq.push( next );
	}
      }
    }
  }
  return 0;
}

int main(){
  while(true){
    int n;
    double vw,vc;
    vector<point> vp;
    vector<line> lines;

    ResetGraph();
    cin >> n;
    if(n==0)break;
    cin >> vw >> vc;
    for(int i = 0; i < n; ++i){
      elem x,y;
      cin>>x>>y;
      point tp(x,y);
      if(i>0){
	line l = make_pair( vp.back(),tp );
	lines.push_back(l);
      }
      vp.push_back(tp);
    }

    for(int i = 0; i < lines.size(); ++i){
      //cout << lines[i].first << ' ' << lines[i].second << endl;
      G[i][i+1] = true;
      W[i][i+1] = dist(lines[i].first, lines[i].second) / vw;
      if( lines[i].second.imag() > lines[i].first.imag() ){
	line l = make_pair( lines[i].first, point(infty, lines[i].first.imag()) );
	for(int j = i+1; j < lines.size(); ++j){
	  //	  cout << l.first << ' ' << l.second << " : " << lines[j].first << ' ' << lines[j].second << endl;
	  if( intersected_seg(l.first,
			      l.second,
			      lines[j].first,
			      lines[j].second) ){
	    point intersect = intersection_seg(
					       l.first,
					       l.second,
					       lines[j].first,
					       lines[j].second );
	    //elem d = dist( intersect, lines[j].second );
	    G[i][j+1] = true;
	    W[i][j+1] = dist( lines[i].first, intersect ) / vc + dist( intersect, lines[j].second ) / vw;
	    break;
	  }
	}
      }
      if( lines[i].second.imag() < lines[i].first.imag() ){
	line l = make_pair( lines[i].second, point(-infty, lines[i].second.imag()) );
	for(int j = i-1; j >= 0; --j){
	  // cout << l.first << ' ' << l.second << " : " << lines[j].first << ' ' << lines[j].second << endl;
	  if( intersected_seg(l.first,
			      l.second,
			      lines[j].first,
			      lines[j].second) ){
	    point intersect = intersection_seg(
					       l.first,
					       l.second,
					       lines[j].first,
					       lines[j].second );
	  //elem d = dist( intersect, lines[j].second );
	    G[j][i+1] = true;
	    W[j][i+1] = dist( lines[i].second, intersect ) / vc + dist( intersect, lines[j].first ) / vw;
	    break;
	  }
	}
      }
    }
    /*
    for(int i = 0; i < N; ++i){
      for(int j = 0; j < N; ++j){
	if( G[i][j] ){
	  cout << "i:" << i << " j:" << j << ' ' << vp[i] << "->" << vp[j] << " COST: "  << W[i][j] << endl;
	}
      }
    }
    */

    printf("%.6lf\n", dijkstra(n-1));
  }
  return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 9888
final_rank: 13

code_snippet: #include<map>
#include<cmath>
#include<vector>
#include<iostream>
#include<queue>
#include<algorithm>
#include<complex>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()
#define pb push_back


const int N = 1000;

class Edge{
public:
  int to;
  double cost;
};

vector<Edge> edge[N];

double dist(double x,double y){
  return sqrt(x*x+y*y);
}

double getx(double xa,double xb,double ya,double yb,double y){
  double A = (ya-yb)/(xa-xb);
  return (y-ya+A*xa)/A;
}

void makeedge(int n,double *x,double *y,double vd,double vwalk){
  rep(i,n-1){
    edge[i].pb((Edge){i+1,dist(x[i]-x[i+1],y[i]-y[i+1])/vwalk});
  }
  
  rep(i,n){
    REP(j,i+1,n-1){
      if (i+1 == j && y[j] <= y[i])break;
      if (y[j+1] <= y[i] && y[i] < y[j]){
	double tx = getx(x[j],x[j+1],y[j],y[j+1],y[i]);
	edge[i].push_back((Edge){j+1,(tx-x[i])/vd+dist(tx-x[j+1],y[i]-y[j+1])/vwalk});
	break;
      }
    }
    
    for(int j=i-1;j>=1;j--){
      if (i-1 == j && y[j] <= y[i])break;
      if (y[j-1] <= y[i] && y[i] < y[j]){
	double tx = getx(x[j],x[j-1],y[j],y[j-1],y[i]);
	edge[j-1].push_back(
			    (Edge){i,(x[i]-tx)/vd+dist(tx-x[j-1],y[i]-y[j-1])/vwalk});
	break;
      }
    }
  }
}


double cost[N];
double solve(int n,double *x,double *y,double vw,double vd){
  rep(i,n)edge[i].clear();
  makeedge(n,x,y,vd,vw);
  rep(i,n)cost[i] = 1e100;

  cost[0] = 0;
  rep(i,n){
    rep(j,edge[i].size()){
      int next = edge[i][j].to;
      cost[next]=min(cost[next],cost[i]+edge[i][j].cost);
    }
  }

  /*
  rep(i,n){
    cout << "now " << x[i] << " " << y[i]<<endl;
    puts("edge begin");
    rep(j,edge[i].size()){
      int nex = edge[i][j].to;
      cout << x[nex] << " "<< y[nex] << " "<< edge[i][j].cost << endl;
    }
    puts("Edge end");
  }
  */

  return cost[n-1];
}


main(){
  int n;
  while(cin>>n && n){
    double vwalk,vd;
    cin>>vwalk>>vd;
    double x[n],y[n];
    rep(i,n)cin>>x[i]>>y[i];
    printf("%6lf\n",solve(n,x,y,vwalk,vd));
  }
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1