Problem: ``Domino effect'' is a famous play using dominoes. A player sets up a chain of dominoes stood. After a chain is formed, the player topples one end of the dominoes. The first domino topples the second domino, the second topples the third and so on.

You are playing domino effect. Before you finish to set up a chain of domino, a domino block started to topple, unfortunately. You have to stop the toppling as soon as possible.

The domino chain forms a polygonal line on a two-dimensional coordinate system without self intersections. The toppling starts from a certain point on the domino chain and continues toward the both end of the chain. If the toppling starts on an end of the chain, the toppling continue toward the other end. The toppling of a direction stops when you touch the toppling point or the toppling reaches an end of the domino chain.

You can assume that:

* You are a point without volume on the two-dimensional coordinate system.
* The toppling stops soon after touching the toppling point.
* You can step over the domino chain without toppling it.



You will given the form of the domino chain, the starting point of the toppling, your coordinates when the toppling started, the toppling velocity and the your velocity. You are task is to write a program that calculates your optimal move to stop the toppling at the earliest timing and calculates the minimum time to stop the toppling.



Input

The first line contains one integer N, which denotes the number of vertices in the polygonal line of the domino chain (2 \leq N \leq 1000). Then N lines follow, each consists of two integers x_{i} and y_{i}, which denote the coordinates of the i-th vertex (-10,000 \leq x, y \leq 10000). The next line consists of three integers x_{t}, y_{t} and v_{t}, which denote the coordinates of the starting point and the velocity of the toppling. The last line consists of three integers x_{p}, y_{p} and v_{p}, which denotes the coordinates of you when the toppling started and the velocity (1 \leq v_{t} \lt v_{p} \leq 10). You may assume that the starting point of the toppling lies on the polygonal line.

Output

Print the minimum time to stop the toppling. The output must have a relative or absolute error less than 10^{-6}.

Examples

Input

2
0 0
15 0
5 0 1
10 10 2


Output

5.0


Input

3
-10 0
0 0
0 10
-1 0 1
3 0 2


Output

4.072027


Input

2
0 0
10 0
5 0 1
9 0 3


Output

2.0

Solution (in CPP):

Solution:
#include<stdio.h>
#include <iostream>
#include <math.h>
#include <numeric>
#include <vector>
#include <map>
#include <functional>
#include <stdio.h>
#include <array>
#include <algorithm>
#include <string>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <queue>
#include<iomanip>
#include<bitset>
#include<stack>
#include<set>
#include<limits>
#include <complex>
using namespace std;



#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()




/* 幾何の基本 */

#include <complex>

typedef long double ld;
typedef complex<ld> Point;

const ld eps = 1e-9, pi = acos(-1.0);

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
}

// 点の入力
Point input_point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// 誤差つき等号判定
bool eq(ld a, ld b) {
	return (abs(a - b) < eps);
}

// 内積
ld dot(Point a, Point b) {
	return real(conj(a) * b);
}

// 外積
ld cross(Point a, Point b) {
	return imag(conj(a) * b);
}

// 直線の定義
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
};

// 円の定義
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// CCW
int ccw(Point a, Point b, Point c) {
	b -= a; c -= a;
	if (cross(b, c) > eps) return 1;   // a,b,cが反時計周りの順に並ぶ
	if (cross(b, c) < -eps) return -1; // a,b,cが時計周りの順に並ぶ
	if (dot(b, c) < 0) return 2;       // c,a,bの順に直線に並ぶ
	if (norm(b) < norm(c)) return -2;  // a,b,cの順に直線に並ぶ
	return 0;                          // a,c,bの順に直線に並ぶ
}


/* 交差判定 */

// 直線と直線の交差判定
bool isis_ll(Line l, Line m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// 直線と線分の交差判定
bool isis_ls(Line l, Line s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// 線分と線分の交差判定
bool isis_ss(Line s, Line t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
		ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

// 点の直線上判定
bool isis_lp(Line l, Point p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// 点の線分上判定
bool isis_sp(Line s, Point p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// 垂線の足
Point proj(Line l, Point p) {
	ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + t * (l.a - l.b);
}

// 直線と直線の交点
Point is_ll(Line s, Line t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}

// 直線と点の距離
ld dist_lp(Line l, Point p) {
	return abs(p - proj(l, p));
}

// 直線と直線の距離
ld dist_ll(Line l, Line m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// 直線と線分の距離
ld dist_ls(Line l, Line s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// 線分と点の距離
ld dist_sp(Line s, Point p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// 線分と線分の距離
ld dist_ss(Line s, Line t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


/* 円 */

// 円と円の交点
vector<Point> is_cc(Circle c1, Circle c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

// 円と直線の交点
vector<Point> is_lc(Circle c, Line l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// 円と線分の距離
vector<Point> is_sc(Circle c, Line l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// 円と点の接線
vector<Line> tangent_cp(Circle c, Point p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// 円と円の接線
vector<Line> tangent_cc(Circle c1, Circle c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), ALL(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}


/* 多角形 */

typedef vector<Point> Polygon;

// 面積
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	REP(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

// 多角形の回転方向
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	REP(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// 円の内外判定
// -1 => out
//  0 => on
//  1 => in
int is_in_polygon(const Polygon &poly, Point p) {
	ld angle = 0;
	int n = poly.size();
	REP(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}

// 凸包
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}

// 凸カット
Polygon convex_cut(const Polygon &ps, Line l) {
	int n = ps.size();
	Polygon Q;
	REP(i, n) {
		Point A = ps[i], B = ps[(i + 1) % n];
		Line m = Line(A, B);
		if (ccw(l.a, l.b, A) != -1) Q.push_back(A);
		if (ccw(l.a, l.b, A) * ccw(l.a, l.b, B) < 0 && isis_ll(l, m))
			Q.push_back(is_ll(l, m));
	}
	return Q;
}


/* アレンジメント */
void add_point(vector<Point> &ps, Point p) {
	for (Point q : ps) if (abs(q - p) < eps) return;
	ps.push_back(p);
}

typedef int Weight;

struct Edge { int from, to; Weight weight; };

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

void add_edge(Graph &g, int from, int to, Weight weight) {
	g[from].push_back(Edge{ from, to, weight });
}

Graph segment_arrangement(const vector<Line> &s, const vector<Point> &p) {
	int n = p.size(), m = s.size();
	Graph g(n);
	REP(i, m) {
		vector<pair<ld, int>> vec;
		REP(j, n) if (isis_sp(s[i], p[j]))
			vec.emplace_back(abs(s[i].a - p[j]), j);
		sort(ALL(vec));
		REP(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			add_edge(g, from, to, abs(p[from] - p[to]));
		}
	}
	return g;
}

Graph circle_arrangement(const vector<Circle> &c, const vector<Point> &p) {
	int n = p.size(), m = c.size();
	Graph g(n);
	REP(i, m) {
		vector<pair<ld, int>> vec;
		REP(j, n) if (abs(abs(c[i].p - p[j]) - c[i].r) < eps)
			vec.emplace_back(arg(c[i].p - p[j]), j);
		sort(ALL(vec));
		REP(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			ld angle = vec[j + 1].first - vec[j].first;
			add_edge(g, from, to, angle * c[i].r);
		}
		if (vec.size() >= 2) {
			int from = vec.back().second, to = vec.front().first;
			ld angle = vec.front().first - vec.back().first;
			add_edge(g, from, to, angle * c[i].r);
		}
	}
	return g;
}


/* 双対グラフ */

// 線分集合は既にアレンジメントされていなければならない．
// 内側の円は時計回りで，外側の円は反時計回りで得られる．
// 変数 polygon は，vector<int> で表される多角形の集合であり，
// vector<int> で表される 多角形のi番目は，その頂点の頂点集合pにおける番号である．
vector<vector<int>> polygon;
vector<int> seg2p[1024][1024];

Graph dual_graph(const vector<Line> &s, const vector<Point> &p) {
	int N = p.size();
	polygon.clear();
	REP(i, 1024) REP(j, 1024) seg2p[i][j].clear();
	vector<vector<tuple<ld, int, bool>>> tup(N);
	REP(i, s.size()) {
		int a = -1, b = -1;
		REP(j, N) if (abs(s[i].a - p[j]) < eps) a = j;
		REP(j, N) if (abs(s[i].b - p[j]) < eps) b = j;
		assert(a >= 0 && b >= 0);
		tup[a].emplace_back(arg(s[i].b - s[i].a), b, false);
		tup[b].emplace_back(arg(s[i].a - s[i].b), a, false);
	}
	REP(i, N) sort(ALL(tup[i]));
	REP(i, N) {
		REP(j, tup[i].size()) {
			ld angle; int pos = j, from = i, to; bool flag;
			tie(angle, to, flag) = tup[i][j];
			if (flag) continue;
			vector<int> ps;
			while (!flag) {
				ps.push_back(from);
				get<2>(tup[from][pos]) = true;
				seg2p[from][to].push_back(polygon.size());
				seg2p[to][from].push_back(polygon.size());
				angle += pi + eps;
				if (angle > pi) angle -= 2 * pi;
				auto it = lower_bound(ALL(tup[to]), make_tuple(angle, 0, false));
				if (it == tup[to].end()) it = tup[to].begin();
				from = to; tie(angle, to, flag) = *it;
				pos = it - tup[from].begin();
			}
			polygon.push_back(ps);
		}
	}
	Graph g(polygon.size());
	REP(i, N) REP(j, i) {
		if (seg2p[i][j].size() == 2) {
			int from = seg2p[i][j][0], to = seg2p[i][j][1];
			g[from].push_back(Edge{ from, to });
			g[to].push_back(Edge{ to, from });
		}
	}
	return g;
}


/* ビジュアライザ */
const ld zoom = 25;
const ld centerX = 6;
const ld centerY = 5;

void change_color(int r, int g, int b) {
	fprintf(stderr, "c.strokeStyle = 'rgb(%d, %d, %d)';\n", r, g, b);
}

int cordx(Point p) { return 400 + zoom * (p.real() - centerX); }
int cordy(Point p) { return 400 - zoom * (p.imag() - centerY); }

#define cord(p) cordx(p),cordy(p)

void draw_point(Point p) {
	fprintf(stderr, "circle(%d, %d, %d)\n", cord(p), 2);
}

void draw_segment(Line l) {
	fprintf(stderr, "line(%d, %d, %d, %d)\n", cord(l.a), cord(l.b));
}

void draw_line(Line l) {
	Point v = l.b - l.a;
	Line m(l.a - v * Point(1e4, 0), l.b + v * Point(1e4, 0));
	fprintf(stderr, "line(%d, %d, %d, %d)\n", cord(m.a), cord(m.b));
}

void draw_polygon(const Polygon &p) {
	int n = p.size();
	REP(i, n) draw_segment(Line(p[i], p[(i + 1) % n]));
}

void draw_circle(Circle c) {
	fprintf(stderr, "circle(%d, %d, %d)\n", cord(c.p), (int)(zoom * c.r));
}





int main() {
	int N; cin >> N;
	vector<Point>ps;
	for (int i = 0; i < N; ++i) {
		int x, y; cin >> x >> y;
		ps.emplace_back(x, y);
	}
	vector<Line>ls;
	for (int i = 0; i < N - 1; ++i) {
		ls.emplace_back(ps[i], ps[i + 1]);
	}
	int dx, dy, dvel; cin >> dx >> dy >> dvel;
	Point dp(dx, dy);
	int snum;
	for (int i = 0; i < N - 1; ++i) {
		if (isis_sp(ls[i], dp)) {
			snum = i;
			break;
		}
	}

	vector<long double>times(N);
	{
		long double nowtime = 0;
		Point np(dp);
		for (int i = snum + 1; i < N; ++i) {
			nowtime += abs(np - ps[i]) / dvel;
			times[i] = nowtime;
			np = ps[i];
		}
	}
	{
		long double nowtime = 0;
		Point np(dp);
		for (int i = snum; i >= 0; --i) {
			nowtime += abs(np - ps[i]) / dvel;
			times[i] = nowtime;
			np = ps[i];
		}
	}
	long double ans = max(times[0], times.back());
	int sx, sy, svel; cin >> sx >> sy >> svel;
	Point sp(sx, sy);
	{
		long double nowtime = 0;
		Point fromp(dp);
		long double fromtime = 0;
		Point np(sp);
		bool flag = false;
		for (int i = snum + 1; i < N; ++i) {
			if ((abs(np-ps[i]) / svel) < times[i]) {
				long double amin = 0;
				long double amax = 1.0;
				while (amin + 1e-10 < amax) {
					long double amid = (amin + amax) / 2;
					long double playertime = abs(np - (ps[i] * amid + fromp*(1 - amid))) / svel;
					long double dominotime = times[i] * amid + fromtime*(1 - amid);
					if (playertime > dominotime) {
						amin = amid;
					}
					else {
						amax = amid;
					}
				}
				nowtime= times[i] * amin + fromtime*(1 - amin);
				np = ps[i] * amin + fromp*(1 - amin);
				flag = true;
				break;
			}
			else {
				fromtime = times[i];
				fromp = ps[i];
			}
		}
		if (flag) {
			ans = min(ans, max(nowtime, times[0]));
			fromp = dp;
			fromtime = 0;
			for (int i = snum; i >= 0; --i) {
				if ((abs(np - ps[i]) / svel)+nowtime < times[i]) {
					long double amin = 0;
					long double amax = 1.0;
					while (amin + 1e-10 < amax) {
						long double amid = (amin + amax) / 2;
						long double playertime = abs(np - (ps[i] * amid + fromp*(1 - amid))) / svel;
						long double dominotime = times[i] * amid + fromtime*(1 - amid);
						if (playertime + nowtime > dominotime) {
							amin = amid;
						}
						else {
							amax = amid;
						}
					}
					nowtime = times[i] * amin + fromtime*(1 - amin);
					ans = min(ans, nowtime);
					np = ps[i] * amin + fromp*(1 - amin);
					flag = true;
					break;
				}
				else {
					fromtime = times[i];
					fromp = ps[i];
				}
			}
		}

	}


	{
		long double nowtime = 0;
		Point fromp(dp);
		long double fromtime = 0;
		Point np(sp);
		bool flag = false;
		for (int i = snum; i >= 0; --i) {
			if ((abs(np - ps[i]) / svel) < times[i]) {
				long double amin = 0;
				long double amax = 1.0;
				while (amin + 1e-15 < amax) {
					long double amid = (amin + amax) / 2;
					long double playertime = abs(np - (ps[i] * amid + fromp*(1 - amid))) / svel;
					long double dominotime = times[i] * amid + fromtime*(1 - amid);
					if (playertime > dominotime) {
						amin = amid;
					}
					else {
						amax = amid;
					}
				}
				nowtime = times[i] * amin + fromtime*(1 - amin);
				np = ps[i] * amin + fromp*(1 - amin);
				flag = true;
				break;
			}
			else {
				fromtime = times[i];
				fromp = ps[i];
			}
		}
		if (flag) {
			ans = min(ans, max(nowtime,times.back()));
			fromp = dp;
			fromtime = 0;
			for (int i = snum + 1; i < N; ++i) {
				if ((abs(np - ps[i]) / svel) + nowtime < times[i]) {
					long double amin = 0;
					long double amax = 1.0;
					while (amin + 1e-15 < amax) {
						long double amid = (amin + amax) / 2;
						long double playertime = abs(np - (ps[i] * amid + fromp*(1 - amid))) / svel;
						long double dominotime = times[i] * amid + fromtime*(1 - amid);
						if (playertime + nowtime > dominotime) {
							amin = amid;
						}
						else {
							amax = amid;
						}
					}
					nowtime = times[i] * amin + fromtime*(1 - amin) ;
					ans = min(ans, nowtime);
					np = ps[i] * amin + fromp*(1 - amin);
					flag = true;
					break;
				}
				else {
					fromtime = times[i];
					fromp = ps[i];
				}
			}
		}

	}
	cout << fixed<<setprecision(32)<<ans << endl;
	return 0;
}