#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;
}
### Prompt

Please create a solution in Cpp to the following problem:

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 (x1, y1) . . . (xn , yn ) as illustlated in the following figure.

<image>

Figure 1: An example route from the castle to the village

Here, xi indicates the distance between the castle and the point i, as the crow flies, and yi indicates the height of the point i. The castle is located on the point (x1 , y1 ), and the village is located on the point (xn , yn).

Red can walk in speed vw . Also, since he has a skill to cut a tunnel through a mountain horizontally, he can move inside the mountain in speed vc.

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
vw vc
x1 y1
...
xn yn


You may assume all the following: n ≤ 1,000, 1 ≤ vw, vc ≤ 10, -10,000 ≤ xi, yi ≤ 10,000, and xi < xj 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.

Example

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

70.710678
100.000000
50.000000
106.066017
150.000000

### Response

```cpp
#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;
}
```