Problem:
Lifeguard in the Pool
プールの監視員
English text is not available in this practice contest.
Horton Moore はプールの監視員として働いている．彼が見回りのためにプールの縁を歩いていたところ，プールの中で一人の少女がおぼれていることに気づいた．もちろん，彼は直ちに救助に向かわなければならない．しかも，少女の身に何かあっては大変であるから，少しでも早く少女のもとにたどり着きたい．
あなたの仕事は，プールの形状（頂点数が 3〜10 の凸多角形），地上および水中における監視員の単位距離あたりの移動時間，そして監視員と少女の初期位置が与えられたときに，監視員が少女のところに到着するまでにかかる最短の時間を求めるプログラムを書くことである．
Input
入力は複数のデータセットの並びからなる．入力の終わりは 1 つの 0 だけを含む行によって示される．
各データセットは次の形式になっている．
n
x
1
y
1
x
2
y
2
...
x
n
y
n
tg
tw
xs
ys
xt
yt
それぞれの記号の意味は次のとおりである．
n
は凸多角形をしたプールの頂点数を示す．これは 3 以上 10 以下の整数である．
(
x
i
,
y
i
) はプールの
i
番目の頂点の座標を示す．それぞれの座標値は絶対値が 100 以下の整数である．頂点は反時計回りの順番で与えられる．
tg
は監視員が地上において移動するときにかかる単位距離あたりの時間を表す．
tw
は監視員が水中において移動するときにかかる単位距離あたりの時間を表す．これらはいずれも整数であり，さらに 1 ≦
tg
<
tw
≦ 100 を満たす．
(
xs
,
ys
) は監視員の初期位置の座標を表す．この座標はプールのちょうど辺上にある．
(
xt
,
yt
) は少女の初期位置の座標を表す．この座標はプールの内側にある．
同一の行にある数値と数値の間は 1 個の空白で区切られている．
この問題において，監視員および少女は点であるとみなす．また，監視員がプールの辺に沿って移動するときは地上を移動しているとみなす．監視員は，地上から水中に一瞬で入ることが，また水中から地上に一瞬で出ることができると仮定して構わない．監視員が地上から水中に，あるいは水中から地上に移るとき，監視員は同じ座標にとどまると考えること．したがって，たとえばプールの縁から離れたところに飛び込むことによって水中での移動距離を減らすことはできない．
Output
各データセットに対して，監視員が少女の元に到着するまでにかかる最短の時間を 1 行に出力しなさい．解答の誤差は 0.00000001 (10
−8
) を超えてはならない．精度に関する条件を満たしていれば，小数点以下は何桁数字を出力しても構わない．
Sample Input
4
0 0 10 0 10 10 0 10
10
12
0 5
9 5
4
0 0 10 0 10 10 0 10
10
12
0 0
9 1
4
0 0 10 0 10 10 0 10
10
12
0 1
9 1
8
2 0 4 0 6 2 6 4 4 6 2 6 0 4 0 2
10
12
3 0
3 5
0
Output for the Sample Input
108.0
96.63324958071081
103.2664991614216
60.0

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for (int i=(a);i<=(b);++i)
#define ROF(i,a,b) for (int i=(a);i>=(b);--i)
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define pDI pair<double,int>
inline int read(){
	int x=0,f=1; char ch=getchar();
	while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
	while (ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); }
	return x*f;
}

const int MAXN=300005;
const double PI=3.141592653589793238462,eps=1e-12,INF=1e20;
#define sqr(x) ((x)*(x))
inline int sgn(double x){ if (fabs(x)<eps) return 0; return x>0?1:-1; }
struct P{
	double x,y,k;
	P(double x=0,double y=0):x(x),y(y){}
	P operator +(const P& p)const{ return P(x+p.x,y+p.y); }
	P operator -(const P& p)const{ return P(x-p.x,y-p.y); }
	P operator *(const double& f)const{ return P(x*f,y*f); }
	P operator /(const double& f)const{ return P(x/f,y/f); }
	double len(){ return sqrt(x*x+y*y); }
	double operator ^(const P& p)const{ return x*p.y-y*p.x; }
	double operator *(const P& p)const{ return x*p.x+y*p.y; }
	bool operator <(const P& p)const{ return k<p.k; }
}A[MAXN],B,C,D,F[MAXN],U,s,t;
inline double dot(P a,P b,P o){ return (a-o)*(b-o); }
inline double cross(P a,P b,P o){ return (a-o)^(b-o); }
inline P ulen(P p){ return p/p.len(); }
inline P projection(P l1,P l2,P p){ return l2+(l1-l2)*dot(l1,p,l2)/sqr(l1-l2); }

struct list{
	int l,lt[MAXN],nt[MAXN],x[MAXN];
	double y[MAXN];
	void clear(){ l=0; memset(lt,0,sizeof(lt)); }
	void addedge(int a,int b,double c){
		//if (l&1) printf("%d-%d %.5f\n",a,b,c);
		nt[++l]=lt[a]; lt[a]=l; x[l]=b; y[l]=c;
	}
}E;

int n,m,l;
double tg,tw,tanalpha,dis[MAXN];
priority_queue<pDI >Q;
double dijkstra(int S,int T){
	FOR(i,1,T) dis[i]=INF;
	Q.push(mp(dis[S]=0,S));
	while (!Q.empty()) {
		pDI z=Q.top(); Q.pop();
		double x=-z.fi; int y=z.se;
		if (dis[y]<x-eps) continue;
		for (int i=E.lt[y];i;i=E.nt[i]) {
			int j=E.x[i];
			if (dis[j]>x+E.y[i]) Q.push(mp(-(dis[j]=x+E.y[i]),j));
		}
	}
	return dis[T];
}
int main(){
	while (n=read(),n!=0) {
		E.clear(),m=0;
		FOR(i,1,n) scanf("%lf%lf",&A[i].x,&A[i].y);
		A[n+1]=A[1]; F[0]=A[0]=A[n];
		scanf("%lf%lf",&tg,&tw);
		//printf("%.5f\n",acos(tg/tw)/PI*180.0);
		scanf("%lf%lf%lf%lf",&s.x,&s.y,&t.x,&t.y);
		if (tw-tg<eps) { printf("%.12f\n",(s-t).len()*tw); continue; }
		tanalpha=tg/sqrt(sqr(tw)-sqr(tg));
		FOR(i,1,n) {
			//printf("%d:\n",i);
			double l1;
			l=m+1;
			U=ulen(A[i+1]-A[i]);
			//printf("%.5f %.5f\n",U.x,U.y);
			B=projection(A[i],A[i+1],s);
			l1=(s-B).len()*tanalpha;
			C=B+U*l1;
			D=B-U*l1;
			//printf("%.5f\n",l1);
			//printf("S-B=(%.5f,%.5f)C=(%.5f,%.5f)D=(%.5f,%.5f)\n",B.x,B.y,C.x,C.y,D.x,D.y);
			if (sgn(dot(A[i],A[i+1],C))<0) F[++m]=C,F[m].k=(C-A[i]).len();
			if (sgn(dot(A[i],A[i+1],D))<0) F[++m]=D,F[m].k=(D-A[i]).len();
			B=projection(A[i],A[i+1],t);
			l1=(t-B).len()*tanalpha;
			C=B+U*l1;
			D=B-U*l1;
			//printf("%.5f\n",l1);
			//printf("T-B=(%.5f,%.5f)C=(%.5f,%.5f)D=(%.5f,%.5f)\n",B.x,B.y,C.x,C.y,D.x,D.y);
			if (sgn(dot(A[i],A[i+1],C))<0) F[++m]=C,F[m].k=(C-A[i]).len();
			if (sgn(dot(A[i],A[i+1],D))<0) F[++m]=D,F[m].k=(D-A[i]).len();
			F[++m]=A[i+1],F[m].k=(A[i+1]-A[i]).len();
			sort(F+l,F+m+1);
			FOR(j,l,m)
			if (j!=1) {
				E.addedge(j-1,j,(F[j]-F[j-1]).len()*tg);
				E.addedge(j,j-1,(F[j]-F[j-1]).len()*tg);
			}
		}
		E.addedge(1,m,(F[m]-F[1]).len()*tg);
		E.addedge(m,1,(F[m]-F[1]).len()*tg);
		F[++m]=s; F[++m]=t;
		FOR(i,1,m) {
			if (i!=m-1) E.addedge(i,m-1,(F[m-1]-F[i]).len()*tw);
			if (i!=m-1) E.addedge(m-1,i,(F[m-1]-F[i]).len()*tw);
			if (i!=m) E.addedge(i,m,(F[m]-F[i]).len()*tw);
			if (i!=m) E.addedge(m,i,(F[m]-F[i]).len()*tw);
		}
		//FOR(i,1,m) printf("ID:%d (%.5f,%.5f)\n",i,F[i].x,F[i].y);
		printf("%.12f\n",dijkstra(m-1,m));
	}
	
	return 0;
}

/*
4
0 0 10 0 10 10 0 10
10
12
0 5
9 5
4
0 0 10 0 10 10 0 10
10
12
0 0
9 1
4
0 0 10 0 10 10 0 10
10
12
0 1
9 1
8
2 0 4 0 6 2 6 4 4 6 2 6 0 4 0 2
10
12
3 0
3 5
0

*/
accuracy: 1
time_ms: 10
memory_kb: 21728
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
#define all(A) A.begin(),A.end()
#define ALL(A) A.begin(),A.end()
#define rep(i, n) for (ll i = 0; i < (ll) (n); i++)
template<class T>
bool chmax(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p < q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

template<class T>
bool chmin(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p > q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

#include<complex>
const int INF = 1000000000;
const ll LINF = 1001002003004005006ll;
int dx[] = { 1,0,-1,0 }, dy[] = { 0,1,0,-1 };

struct IOSetup {
    IOSetup() {
        cin.tie(0);
        ios::sync_with_stdio(0);
        cout << fixed << setprecision(12);
    }
} iosetup;

template<typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    return os;
}
template<typename T>
istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v)is >> x;
    return is;
}

// line 1 "Geometry/template.cpp"
// Real
using Real = double;
const Real EPS = 1e-6;
const Real pi = acosl(-1);

// Point
using Point = complex<Real>;
istream& operator>>(istream& is, Point& p) {
    Real a, b;
    is >> a >> b;
    p = Point(a, b);
    return is;
}
ostream& operator<<(ostream& os, Point& p) {
    return os << fixed << setprecision(12) << p.real() << ' ' << p.imag();
}
inline bool eq(Real a, Real b) {
    return fabs(a - b) < EPS;
}
Point operator*(const Point& p, const Real& d) {
    return Point(real(p) * d, imag(p) * d);
}

// Line
struct Line {
    Point p1, p2;
    Line() = default;
    Line(Point p1, Point p2) :p1(p1), p2(p2) {}
    //Ax + By = C
    Line(Real A, Real B, Real C) {
        if (eq(A, 0))     p1 = Point(0, C / B), p2 = Point(1, C / B);
        else if (eq(B, 0))p1 = Point(C / A, 0), p2 = Point(C / A, 1);
        else            p1 = Point(0, C / B), p2 = Point(C / A, 0);
    }
};

// Segment
struct Segment :Line {
    Segment() = default;
    Segment(Point p1, Point p2) :Line(p1, p2) {}
};
Real dot(Point a, Point b) {
    return real(a) * real(b) + imag(a) * imag(b);
}
Real cross(Point a, Point b) {
    return real(a) * imag(b) - imag(a) * real(b);
}
int ccw(Point a, Point b, Point c) {
    b -= a; c -= a;
    if (cross(b, c) > EPS)       return  1;//COUNTER CLOCKWISE
    else if (cross(b, c) < -EPS) return -1;//CLOCKWISE
    else if (dot(b, c) < 0)      return  2;//c--a--b ONLINE BACK
    else if (norm(b) < norm(c)) return -2;//a--b--c ONLINE FRONT
    else                     return  0;//a--c--b ON SEGMENT
}
Point projection(Segment l, Point p) {
    Real k = dot(l.p1 - l.p2, p - l.p1) / norm(l.p1 - l.p2);
    return l.p1 + (l.p1 - l.p2) * k;
}
bool intersect(Segment s, Point p) {
    return ccw(s.p1, s.p2, p) == 0;
}
Real dis(Point a, Point b) {
    return abs(a - b);
}
Real dis(Segment s, Point p) {
    Point r = projection(s, p);
    if (intersect(s, r)) return abs(r - p);
    return min(abs(s.p1 - p), abs(s.p2 - p));
}

// //AtoBで途中から水でPへ
pair<double, Point> min_point(Point P, Point A, Point B, double G, double W) {
    double res = min(dis(P, A) * W, dis(P, B) * W + dis(A, B) * G);
    double L = 0.0, R = 1.0;
    Point D = B - A;
    rep(i, 100) {
        double c1 = (L * 2.0 + R) / 3.0;
        double c2 = (L + 2.0 * R) / 3.0;
        Point P1, P2;

        P1 = { A.real() + c1 * D.real(),A.imag() + c1 * D.imag() };
        P2 = { A.real() + c2 * D.real(),A.imag() + c2 * D.imag() };
        double d1 = dis(P, P1) * W + dis(A, P1) * G;
        double d2 = dis(P, P2) * W + dis(A, P2) * G;
        if (d1 < d2) {
            R = c2;
        }
        else {
            L = c1;
        }
    }
    Point P1;
    P1 = Point({ A.real() + L * D.real(),A.imag() + L * D.imag() });
    return { dis(P,P1) * W + dis(A,P1) * G,P1 };
}

void solve(ll N) {
    vector<Point> P(N);
    rep(i, N) {
        cin >> P[i];
    }
    double G, W;
    cin >> G >> W;
    cout << fixed << setprecision(14);
    Point S, T;
    cin >> S >> T;
    double an = dis(S, T) * W;
    double bn=1e18;
    rep(_, 2) {
        ll bs = 0;
        rep(i, N) {
            if (dis(Segment(P[i], P[(i + 1) % N]), S) < EPS * 2.0) {
                bs = i;
                break;
            }
        }
        double RUN = 0.0;
        for (ll i = bs; i < bs + N; i++) {
            if (i == bs) {
                pair<double, Point> dP = min_point(T, S, P[(i + 1) % N], G, W);
                double d = dP.first;
                Point H = dP.second;
                an = min(an, d);
                RUN += dis(S, P[(i + 1) % N]) * G;
            }
            else {
                pair<double, Point> dP = min_point(T, P[i%N], P[(i + 1) % N], G, W);
                double d = dP.first;
                Point H = dP.second;
                an = min(an, d + RUN);
                RUN += dis(P[i%N], P[(i + 1) % N]) * G;

                for(ll j=bs+1;j<=i;j++){
                    pair<double, Point> dQ = min_point(S, P[(j+1)%N], P[j%N], G, W);
                    
                    double d2 = dQ.first;
                    Point H2 = dQ.second;
                    if(j==i){
                        if(dis(H,P[i%N])+dis(H2,P[(i+1)%N])<dis(P[i%N],P[(i+1)%N]))continue;
                        double dn=d+d2-dis(P[i%N],P[(i+1)%N])*G;
                        
                        an=min(an,dn);
                    }
                    else{
                        double ru=0.0;
                        for(ll k=j+1;k<i;k++){
                            ru+=dis(P[k%N],P[(k+1)%N])*G;
                        }
                        double dn=d+d2+ru;
                        an=min(an,d+d2+ru);    
                    }
                    
                }
            }
            
        }
        reverse(all(P));
    }

    cout << an << endl;
    return;
}


int main() {

    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    ll N;
    while (cin >> N, N != 0)solve(N);

}
accuracy: 1
time_ms: 180
memory_kb: 3400
final_rank: 12

code_snippet: #include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

struct Point {
	double px, py;
};

Point operator+(const Point &a1, const Point &a2) {
	return Point{ a1.px + a2.px, a1.py + a2.py };
}

Point operator-(const Point &a1, const Point &a2) {
	return Point{ a1.px - a2.px, a1.py - a2.py };
}

Point operator*(const Point &a1, const double &a2) {
	return Point{ a1.px * a2, a1.py * a2 };
}

double ABS(Point A1) {
	return sqrt(A1.px * A1.px + A1.py * A1.py);
}

double crs(Point A1, Point A2) {
	return A1.px * A2.py - A1.py * A2.px;
}

int N, Guard_Idx;
Point G[309], S, T;
double TG, TW, dist_sum[309], dist_pos[309];
double dist[309][309];

Point GetPoint(int idx, double prog) {
	Point P1 = G[(idx + 0) % N];
	Point P2 = G[(idx + 1) % N];
	return P1 + ((P2 - P1) * prog);
}

void solve() {
	// Initialize
	dist_sum[0] = 0;
	for (int i = 0; i < N; i++) dist_pos[i] = ABS(G[i] - G[(i + 1) % N]);
	for (int i = 0; i < N; i++) dist_sum[i + 1] = dist_sum[i] + dist_pos[i];
	G[N] = S;
	G[N + 1] = T;
	
	// Get Place of S
	vector<pair<int, double>> Candidate;
	for (int i = 0; i < N; i++) {
		Point P1 = G[(i + 0) % N];
		Point P2 = G[(i + 1) % N];
		Point P3 = S;
		if (abs(crs(P2 - P1, P3 - P1)) < 1.0e-6) {
			Guard_Idx = i;
			Candidate.push_back(make_pair(i, ABS(P3 - P1) / ABS(P2 - P1)));
			break;
		}
	}
	
	// Find Candidate
	for (int i = 0; i < N; i++) Candidate.push_back(make_pair(i, 0.0));
	for (int i = 0; i <= N + 1; i++) {
		for (int j = 0; j < N; j++) {
			int idx1 = (j + 0) % N;
			int idx2 = (j + 1) % N;
			if (idx1 == i || idx2 == i) continue;
			
			// Ternary Search 1
			if (true) {
				double cl = 0.0, cr = 1.0, c1, c2;
				for (int k = 0; k < 90; k++) {
					c1 = (cl + cl + cr) / 3.0;
					c2 = (cl + cr + cr) / 3.0;
					Point P1 = G[i];
					Point P2 = GetPoint(j, c1);
					Point P3 = GetPoint(j, c2);
					double dist1 = ABS(P2 - P1) * TW + (1.0 - c1) * dist_pos[j] * TG;
					double dist2 = ABS(P3 - P1) * TW + (1.0 - c2) * dist_pos[j] * TG;
					if (dist1 > dist2) { cl = c1; }
					else { cr = c2; }
				}
				// cout << "# " << i << " " << j << " " << cl << endl;
				Candidate.push_back(make_pair(j, cl));
			}
			
			// Ternary Search 2
			if (true) {
				double cl = 0.0, cr = 1.0, c1, c2;
				for (int k = 0; k < 90; k++) {
					c1 = (cl + cl + cr) / 3.0;
					c2 = (cl + cr + cr) / 3.0;
					Point P1 = G[i];
					Point P2 = GetPoint(j, c1);
					Point P3 = GetPoint(j, c2);
					double dist1 = ABS(P2 - P1) * TW + c1 * dist_pos[j] * TG;
					double dist2 = ABS(P3 - P1) * TW + c2 * dist_pos[j] * TG;
					if (dist1 > dist2) { cl = c1; }
					else { cr = c2; }
				}
				// cout << "# " << i << " " << j << " " << cl << endl;
				Candidate.push_back(make_pair(j, cl));
			}
		}
	}
	int NumCand = Candidate.size();
	Candidate.push_back(make_pair(-1.0, -1.0));
	
	// Get Distance
	for (int i = 0; i <= NumCand; i++) {
		for (int j = 0; j <= NumCand; j++) {
			Point P1 = T; if (i < NumCand) P1 = GetPoint(Candidate[i].first, Candidate[i].second);
			Point P2 = T; if (j < NumCand) P2 = GetPoint(Candidate[j].first, Candidate[j].second);
			dist[i][j] = ABS(P1 - P2) * TW;
			if (i < NumCand && j < NumCand) {
				double r1 = dist_sum[Candidate[i].first] + dist_pos[Candidate[i].first] * Candidate[i].second;
				double r2 = dist_sum[Candidate[j].first] + dist_pos[Candidate[j].first] * Candidate[j].second;
				double ground = min(abs(r1 - r2), dist_sum[N] - abs(r1 - r2));
				dist[i][j] = min(dist[i][j], ground * TG);
			}
		}
	}
	
	// Warshall-Floyd
	for (int k = 0; k <= NumCand; k++) {
		for (int i = 0; i <= NumCand; i++) {
			for (int j = 0; j <= NumCand; j++) dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
		}
	}
	
	// Output
	printf("%.12lf\n", dist[0][NumCand]);
}

int main() {
	while (true) {
		// Input
		cin >> N;
		for (int i = 0; i < N; i++) cin >> G[i].px >> G[i].py;
		if (N == 0) break;
		cin >> TG >> TW;
		cin >> S.px >> S.py;
		cin >> T.px >> T.py;
		
		// Solve
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 1210
memory_kb: 4092
final_rank: 16

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i = 0; i < (n); i++)
using namespace std;
typedef long long ll;
using Real = double;
using Point = complex< double >;
using Polygon = vector< Point >;
const Real EPS = 1e-10, PI = acos(-1);
constexpr int COUNTER_CLOCKWISE = +1;
constexpr int CLOCKWISE = -1;
constexpr int ONLINE_BACK = +2;  // c-a-b
constexpr int ONLINE_FRONT = -2; // a-b-c
constexpr int ON_SEGMENT = 0;    // a-c-b

Point operator*(const Point &p, const Real &d) {
    return Point(real(p) * d, imag(p) * d);
}

Point operator/(const Point &p, const Real &d) {
    return Point(real(p) / d, imag(p) / d);
}

istream &operator>>(istream &is, Point &p) {
    Real a, b; is >> a >> b;
    p = Point(a, b);
    return is;
}

ostream &operator<<(ostream &os, const Point &p) {
    return os << fixed << setprecision(10) << real(p) << " " << imag(p);
}

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

// 符号
inline int sign(const Real &r) {
    return r <= -EPS ? -1 : r >= EPS ? 1 : 0;
}

// a = b ? 
inline bool equals(const Real &a, const Real &b) {
    return sign(a - b) == 0;
}


// 単位ベクトル
Point unitVec(const Point &a){ return a / abs(a); }

// 法線ベクトル 半時計周り
Point normVec(const Point &a){ return a * Point(0, 1); }
//Point normVec(const Point &a){ return a * Point(0,-1); }

// 内積
Real dot(const Point &a, const Point &b) {
    return (a.real() * b.real() + a.imag() * b.imag());
}

// 外積
Real cross(const Point &a, const Point &b) {
    return (a.real() * b.imag() - a.imag() * b.real());
}

Point rotate(const Point &p, const Real &theta) {
    return Point(cos(theta) * p.real() - sin(theta) * p.imag(),
                 sin(theta) * p.real() + cos(theta) * p.imag());
}

Real Radian_To_Degree(const Real &radian){ return radian * 180.0 / PI; }
Real Degree_To_Radian(const Real &degree){ return degree * PI / 180.0; }

struct Line {
    Point a, b;
    Line() = default;
    Line(Point a, Point b) : a(a), b(b) {}

    // Ax + By = C
    Line(Real A, Real B, Real C) {
        if(equals(A, 0)) {
            a = Point(0, C / B), b = Point(1, C / B);
        }else if(equals(B,0)) {
            b = Point(C / A, 0), b = Point(C / A, 1);
        }else{
            a = Point(0, C / B), b = Point(C / A, 0);
        }
    }

    friend ostream &operator<<(ostream &os, Line &p) {
        return os << p.a << " " << p.b;
    }

    friend istream &operator>>(istream &is, Line &a) {
        return is >> a.a >> a.b;
    }
};

struct Segment : Line {
    Segment() = default;
    Segment(Point a, Point b) : Line(a, b) {}
};

struct Circle {
    Point p;
    Real r;
    Circle() = default;
    Circle(Point p, Real r) : p(p), r(r) {}

    friend ostream &operator<<(ostream &os, Circle &c) {
        return os << c.p << " " << c.r;
    }

    friend istream &operator>>(istream &is, Circle &c) {
        return is >> c.p >> c.r;
    }
};

// 直線lに点pから引いた垂線の足を求める
Point projection(const Line &l, const Point &p) {
    Real t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}

Point projection(const Segment &l, const Point &p) {
    Real t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}

// 直線lに関して点pと対称な点を求める
Point reflection(const Line &l, const Point &p) {
    return p + (projection(l, p) - p) * 2.0;
}

// 点の回転方向
// 点aを基準に点b,cの位置関係
int ccw(const Point &a, Point b, Point c) {
    b = b - a, c = c - a;
    if(sign(cross(b, c)) == +1) return COUNTER_CLOCKWISE; // 反時計回り
    if(sign(cross(b, c)) == -1) return CLOCKWISE;         // 時計回り
    if(sign(dot(b, c)) == -1) return ONLINE_BACK;         // c - a - b
    if(norm(b) < norm(c)) return ONLINE_FRONT;            // a - b - c
    return ON_SEGMENT;                                    // a - c - b
}

// 2直線の直交判定
bool is_orthogonal(const Line &a, const Line &b) {
    return equals(dot(a.b - a.a, b.b - b.a), 0);
}

// 2直線の平行判定
bool is_parallel(const Line &a, const Line &b) {
    return equals(cross(a.b - a.a, b.b - b.a), 0);
}

// 線分の交差判定
bool is_intersect_ss(const Segment &s, const Segment &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 is_intersect_ll(const Line &l, const Line &m) {
    Real A = cross(l.b - l.a, m.b - m.a);
    Real B = cross(l.b - l.a, l.b - m.a);
    if(equals(abs(A), 0) && equals(abs(B), 0)) return true;
    return !is_parallel(l, m);
}

// 線分に点が乗っているか
bool is_intersect_sp(const Segment &s, const Point &p) {
    return ccw(s.a, s.b, p) == ON_SEGMENT;
}

// 点と点の距離
Real distance_pp(const Point &p1, const Point &p2) {
    return sqrt(pow(real(p1)-real(p2), 2) + pow(imag(p1)-imag(p2), 2));
}

// 点と直線の距離
Real distance_lp(const Line &l, const Point &p) {
    return abs(p - projection(l, p));
}

// 直線と直線の距離
Real distance_ll(const Line &l, const Line &m) {
    return is_intersect_ll(l, m) ? 0 : distance_lp(l, m.a);
}

// 点と線分の距離
Real distance_sp(const Segment &s, const Point &p) {
    Point r = projection(s, p);
    if(is_intersect_sp(s, r)) return abs(r - p);
    return min(abs(s.a - p), abs(s.b - p));
}

// 線分と線分の距離
Real distance_ss(const Segment &a, const Segment &b) {
    if(is_intersect_ss(a, b)) return 0;
    return min({distance_sp(a, b.a), distance_sp(a, b.b), distance_sp(b, a.a), distance_sp(b, a.b)});
}

// 交点
Point cross_point_ll(const Line &l, const Line &m) {
    Real A = cross(l.b - l.a, m.b - m.a);
    Real B = cross(l.b - l.a, l.b - m.a);
    if(equals(abs(A), 0) && equals(abs(B), 0)) return m.a;
    return m.a + (m.b - m.a) * B / A;
}

// 円と円の位置関係
int intersect(Circle c1, Circle c2) {
    if(c1.r < c2.r) swap(c1, c2);
    Real d = abs(c1.p - c2.p);
    if(c1.r + c2.r < d) return 4;
    if(equals(c1.r + c2.r, d)) return 3;
    if(c1.r - c2.r < d) return 2;
    if(equals(c1.r - c2.r, d)) return 1;
    return 0;
}

Real area(const Polygon &p){
    Real A = 0;
    for(int i = 0; i < p.size(); i++){
        A += cross(p[i], p[(i + 1) % p.size()]);
    }
    return A * 0.5;
}

bool is_convex(const Polygon &p){
    for(int i = 0; i < p.size(); i++){
        if(ccw(p[(i + p.size() - 1) % p.size()], p[i], p[(i + 1) % p.size()]) == -1) return false;
    }
    return true;
}

enum { OUT, ON, IN };
int contains(const Polygon &Q, const Point &p){
    bool in = false;
    for(int i = 0; i < Q.size(); i++){
        Point a = Q[i] - p, b = Q[(i + 1) % Q.size()] - p;
        if(a.imag() > b.imag()) swap(a, b);
        if(a.imag() <= 0 && 0 < b.imag() && cross(a, b) < 0) in = !in;
        if(cross(a, b) == 0 && dot(a, b) <= 0) return ON;
    }
    return in ? IN : OUT;
}

Polygon convex_hull(Polygon &p, bool strict = true){
    int n = (int)p.size(), k = 0;
    if(n <= 2) return p;
    sort(p.begin(), p.end());
    Polygon ch(2 * n);
    for(int i = 0; i < n; ch[k++] = p[i++]){
        while(k >= 2 && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
    }
    for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]){
        while(k >= t && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
    }
    ch.resize(k - 1);
    return ch;
}

Real convex_diameter(const Polygon &p){
    int n = (int)p.size();
    int is = 0, js = 0;
    for(int i = 1; i < n; i++){
        if(p[i].imag() > p[is].imag()) is = i;
        if(p[i].imag() < p[js].imag()) js = i;
    }
    Real maxdis = norm(p[is] - p[js]);
    int maxi, maxj, i, j;
    i = maxi = is;
    j = maxj = js;
    do {
        if(cross(p[(i + 1) % n] - p[i], p[(j + 1) % n] - p[j]) >= 0){
            j = (j + 1) % n;
        }else{
            i = (i + 1) % n;
        }

        if(norm(p[i] - p[j]) > maxdis){
            maxdis = norm(p[i] - p[j]);
            maxi = i;
            maxj = j;
        }

    }while(i != is || j != js);
    return sqrt(maxdis);
}

Polygon convex_cut(const Polygon &U, Line l){
    Polygon ret;
    for(int i = 0; i < U.size(); i++){
        Point now = U[i], nxt = U[(i + 1) % U.size()];
        if(ccw(l.a, l.b, now) != -1) ret.push_back(now);
        if(ccw(l.a, l.b, now) * ccw(l.a, l.b, nxt) < 0){
            ret.push_back(cross_point_ll(Line(now, nxt), l));
        }
    }
    return ret;
}

Real ClosetPair(Polygon& ps){
    if(ps.size() <= 1) throw (0);
    sort(begin(ps), end(ps));

    auto compare_y = [&](const Point &a, const Point &b) {
        return a.imag() < b.imag();
    };
    Polygon beet(ps.size());
    const double INF = 1e18;

    function< double(int, int) > rec = [&](int left, int right) {
        if(right - left <= 1) return INF;
        int mid = (left + right) >> 1;
        auto x = ps[mid].real();
        auto ret = min(rec(left, mid), rec(mid, right));
        inplace_merge(begin(ps) + left, begin(ps) + mid, begin(ps) + right, compare_y);
        int ptr = 0;
        for(int i = left; i < right; i++) {
            if(fabs((ps[i].real()) - x) >= ret) continue;
            for(int j = 0; j < ptr; j++) {
                auto luz = ps[i] - beet[ptr - j - 1];
                if(luz.imag() >= ret) break;
                ret = min(ret, abs(luz));
            }
            beet[ptr++] = ps[i];
        }
        return ret;
    };
    return rec(0, (int) ps.size());
}

pair< Point, Point > cross_point_cc(const Circle &c1, const Circle &c2) {
    Real d = abs(c1.p - c2.p);
    Real a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
    Real t = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
    Point p1 = c1.p + Point(cos(t + a) * c1.r, sin(t + a) * c1.r);
    Point p2 = c1.p + Point(cos(t - a) * c1.r, sin(t - a) * c1.r);
    return {p1, p2};
}

const int BOTTOM = 0;
const int LEFT   = 1;
const int RIGHT  = 2;
const int TOP    = 3;

class endPoint {
    public:
        Point p;
        int seg; // id of Point
        int st; // kind of Point
        endPoint(){}
        endPoint(Point inp, int inseg, int inst):p(inp),seg(inseg),st(inst){}
        bool operator<(const endPoint &ep)const {
            if(p.imag() == ep.p.imag()) return st < ep.st;
            else return p.imag() < ep.p.imag();
        }
};

endPoint EP[220000];
int Manhattan_Intersections(vector< Segment > s){
    int n = s.size();
    double hoge;

    for(int i = 0, k = 0; i < n; i++){
        if(s[i].a.imag() == s[i].b.imag()){
            if(s[i].a.real() > s[i].b.real()){
                hoge = s[i].a.real();
                s[i].a.real(s[i].b.real());
                s[i].b.real(hoge);
            }
        }else if(s[i].a.imag() > s[i].b.imag()){
            hoge = s[i].a.imag();
            s[i].a.imag(s[i].b.imag());
            s[i].b.imag(hoge);
        }

        if(s[i].a.imag() == s[i].b.imag()){
            EP[k++] = endPoint(s[i].a, i, LEFT);
            EP[k++] = endPoint(s[i].b, i, RIGHT);
        }else{
            EP[k++] = endPoint(s[i].a, i, BOTTOM);
            EP[k++] = endPoint(s[i].b, i, TOP);
        }
    }

    sort(EP, EP + 2 * n);
    set<int> BT;
    BT.insert(1000000001);
    int cnt = 0;
    for(int i = 0; i < 2 * n; i++){
        if(EP[i].st == TOP) BT.erase(EP[i].p.real());
        else if(EP[i].st == BOTTOM) BT.insert(EP[i].p.real());
        else if(EP[i].st == LEFT){
            set<int>::iterator b = lower_bound(BT.begin(), BT.end(), s[EP[i].seg].a.real());
            set<int>::iterator e = upper_bound(BT.begin(), BT.end(), s[EP[i].seg].b.real());
            cnt += distance(b, e);
        }
    }

    return cnt;
}

// 内接円
Circle Inscribed_Circle(const Point& a, const Point& b, const Point& c){
    double A = abs(b - c), B = abs(c - a), C = abs(a - b);
    Point x = Point((a * A + b * B + c * C) / (A + B + C));
    double r = distance_sp(Segment(a,b),x);
    return Circle(x, r);
}

// 外接円
Circle Circumscribed_Circle(const Point& a, const Point& b, const Point& c){
    Point m1((a+b)/2.0), m2((b+c)/2.0);
    Point v((b-a).imag(), (a-b).real()), w((b-c).imag(), (c-b).real());
    Line s(m1, Point(m1+v)), t(m2, Point(m2+w));
    const Point x = cross_point_ll(s, t);
    return Circle(x, abs(a-x));
}

pair< Point, Point > cross_point_cl(const Circle &c, const Line &l) {
    Point pr = projection(l, c.p);
    if(equals(abs(pr - c.p), c.r)) return {pr, pr};
    Point e = (l.b - l.a) / abs(l.b - l.a);
    auto k = sqrt(norm(c.r) - norm(pr - c.p));
    return {pr - e * k, pr + e * k};
}

// 点pを通る円の接線
pair<Point,Point> tangent_cp(const Circle &c, const Point &p) {
    return cross_point_cc(c, Circle(p, sqrt(norm(c.p - p) - c.r * c.r)));
}

// 二つの円の共通接線
vector< Line > tangent_cc(Circle c1, Circle c2){
    vector< Line > ret;
    if(c1.r < c2.r) swap(c1,c2);
    double g = norm(c1.p-c2.p);
    if(equals(g,0.0)) return ret;
    Point u = (c2.p-c1.p)/sqrt(g);
    Point v = rotate(u, PI * 0.5);
    for(int s:{-1,1}){
        double h = (c1.r+ s*c2.r)/sqrt(g);
        if(equals(1- h*h, 0)){
            ret.emplace_back(c1.p+u*c1.r, c1.p+(u+v)*c1.r);
        }else if(1-h*h > 0){
            Point uu = u*h, vv = v*sqrt(1-h*h);
            ret.emplace_back(c1.p+(uu+vv)*c1.r, c2.p-(uu+vv)*c2.r*s);
            ret.emplace_back(c1.p+(uu-vv)*c1.r, c2.p-(uu-vv)*c2.r*s);
        }
    }
    return ret;
}

Real area_poly_c(const Polygon &p, const Circle &c) {
    if(p.size() < 3) return 0.0;
    function< Real(Circle, Point, Point) > cross_area = [&](const Circle &c, const Point &a, const Point &b) {
        Point va = c.p - a, vb = c.p - b;
        Real f = cross(va, vb), ret = 0.0;
        if(equals(f, 0.0)) return ret;
        if(max(abs(va), abs(vb)) < c.r + EPS) return f;
        if(distance_sp(Segment(a, b), c.p) > c.r - EPS) return c.r * c.r * arg(vb * conj(va));
        auto u = cross_point_cl(c, Segment(a, b));
        vector< Point > tot{a, u.first, u.second, b};
        for(int i = 0; i + 1 < tot.size(); i++) {
            ret += cross_area(c, tot[i], tot[i + 1]);
        }
        return ret;
    };
    Real A = 0;
    for(int i = 0; i < p.size(); i++) {
        A += cross_area(c, p[i], p[(i + 1) % p.size()]);
    }
    return A;
}

Real area_cc(const Circle &c1, const Circle &c2) {
    Real d = abs(c1.p - c2.p);
    if(c1.r + c2.r <= d + EPS) return 0.0;
    if(d <= fabs(c1.r - c2.r) + EPS) {
        Real r = min(c1.r, c2.r);
        return r * r * PI;
    }
    Real rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
    Real theta = acos(rc / c1.r);
    Real phi = acos((d - rc) / c2.r);
    return (c1.r * c1.r*theta + c2.r*c2.r*phi - d*c1.r*sin(theta));
}

// g <- pair < v , cost > 
template < class T >
vector<T> Dijkstra(vector<vector<pair<int,T>>> &g, int s) {
    vector<T> dist(g.size(), -1);
    priority_queue<pair<T,int>> Q;
    Q.emplace(0, s);
    while(!Q.empty()){
        T cost = Q.top().first;
        int v = Q.top().second;
        Q.pop();
        cost = - cost;
        if(dist[v] == -1){
            dist[v] = cost;
            for(auto e : g[v]){
                if(dist[e.first] == -1){
                    Q.emplace(-(cost + e.second), e.first);
                }
            }
        }
    }
    return dist;
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(0);

    while(true) {
        int n; cin >> n; if(n == 0) break;
        Polygon p(n);
        rep(i,n) cin >> p[i];
        Real tg,tw; cin >> tg >> tw;
        Point s,t; cin >> s >> t;

        auto f = [&](Segment l, Point q) {
            Point lo = l.a, hi = l.b;
            rep(_,50) {
                Point m1 = (lo + lo + hi) / 3.0;
                Point m2 = (lo + hi + hi) / 3.0;
                auto get = [&](Point x) { return abs(x - l.a) * tg + abs(x - q) * tw; };
                if(get(m1) > get(m2)) lo = m1; else hi = m2;
            }
            return lo;
        };

        vector< Point > v; v.push_back(s); v.push_back(t);
        rep(i,n){
            Segment l(p[i], p[(i + 1) % n]), r(p[(i + 1) % n], p[i]);
            rep(j,n) if(i != j) {
                v.push_back(f(l, p[j]));
                v.push_back(f(r, p[j])); 
            }
            v.push_back(f(l, s)); v.push_back(f(r, s));
            v.push_back(f(r, t)); v.push_back(f(l, t));
        }

        int M = v.size();
        vector<vector< Real >> d(M, vector< Real >(M, 1e9));
        rep(i,M)rep(j,M) {
            d[i][j] = d[j][i] = abs(v[i] - v[j]) * tw;
            rep(k,n) {
                if(is_intersect_sp(Segment(p[k], p[(k + 1) % n]), v[i])
                && is_intersect_sp(Segment(p[k], p[(k + 1) % n]), v[j]))
                        d[i][j] = d[j][i] = min(d[i][j], abs(v[i] - v[j]) * tg);
            }
        }
        
        rep(k,M)rep(i,M)rep(j,M) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
        cout.precision(17);
        cout << d[0][1] << endl;
    }
}
accuracy: 1
time_ms: 2250
memory_kb: 9000
final_rank: 17

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i = 0; i < (n); i++)
using namespace std;
typedef long long ll;
using Real = double;
using Point = complex< double >;
using Polygon = vector< Point >;
const Real EPS = 1e-10, PI = acos(-1);
constexpr int COUNTER_CLOCKWISE = +1;
constexpr int CLOCKWISE = -1;
constexpr int ONLINE_BACK = +2;  // c-a-b
constexpr int ONLINE_FRONT = -2; // a-b-c
constexpr int ON_SEGMENT = 0;    // a-c-b

Point operator*(const Point &p, const Real &d) {
    return Point(real(p) * d, imag(p) * d);
}

Point operator/(const Point &p, const Real &d) {
    return Point(real(p) / d, imag(p) / d);
}

istream &operator>>(istream &is, Point &p) {
    Real a, b; is >> a >> b;
    p = Point(a, b);
    return is;
}

ostream &operator<<(ostream &os, const Point &p) {
    return os << fixed << setprecision(10) << real(p) << " " << imag(p);
}

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

// 符号
inline int sign(const Real &r) {
    return r <= -EPS ? -1 : r >= EPS ? 1 : 0;
}

// a = b ? 
inline bool equals(const Real &a, const Real &b) {
    return sign(a - b) == 0;
}


// 単位ベクトル
Point unitVec(const Point &a){ return a / abs(a); }

// 法線ベクトル 半時計周り
Point normVec(const Point &a){ return a * Point(0, 1); }
//Point normVec(const Point &a){ return a * Point(0,-1); }

// 内積
Real dot(const Point &a, const Point &b) {
    return (a.real() * b.real() + a.imag() * b.imag());
}

// 外積
Real cross(const Point &a, const Point &b) {
    return (a.real() * b.imag() - a.imag() * b.real());
}

Point rotate(const Point &p, const Real &theta) {
    return Point(cos(theta) * p.real() - sin(theta) * p.imag(),
                 sin(theta) * p.real() + cos(theta) * p.imag());
}

Real Radian_To_Degree(const Real &radian){ return radian * 180.0 / PI; }
Real Degree_To_Radian(const Real &degree){ return degree * PI / 180.0; }

struct Line {
    Point a, b;
    Line() = default;
    Line(Point a, Point b) : a(a), b(b) {}

    // Ax + By = C
    Line(Real A, Real B, Real C) {
        if(equals(A, 0)) {
            a = Point(0, C / B), b = Point(1, C / B);
        }else if(equals(B,0)) {
            b = Point(C / A, 0), b = Point(C / A, 1);
        }else{
            a = Point(0, C / B), b = Point(C / A, 0);
        }
    }

    friend ostream &operator<<(ostream &os, Line &p) {
        return os << p.a << " " << p.b;
    }

    friend istream &operator>>(istream &is, Line &a) {
        return is >> a.a >> a.b;
    }
};

struct Segment : Line {
    Segment() = default;
    Segment(Point a, Point b) : Line(a, b) {}
};

struct Circle {
    Point p;
    Real r;
    Circle() = default;
    Circle(Point p, Real r) : p(p), r(r) {}

    friend ostream &operator<<(ostream &os, Circle &c) {
        return os << c.p << " " << c.r;
    }

    friend istream &operator>>(istream &is, Circle &c) {
        return is >> c.p >> c.r;
    }
};

// 直線lに点pから引いた垂線の足を求める
Point projection(const Line &l, const Point &p) {
    Real t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}

Point projection(const Segment &l, const Point &p) {
    Real t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}

// 直線lに関して点pと対称な点を求める
Point reflection(const Line &l, const Point &p) {
    return p + (projection(l, p) - p) * 2.0;
}

// 点の回転方向
// 点aを基準に点b,cの位置関係
int ccw(const Point &a, Point b, Point c) {
    b = b - a, c = c - a;
    if(sign(cross(b, c)) == +1) return COUNTER_CLOCKWISE; // 反時計回り
    if(sign(cross(b, c)) == -1) return CLOCKWISE;         // 時計回り
    if(sign(dot(b, c)) == -1) return ONLINE_BACK;         // c - a - b
    if(norm(b) < norm(c)) return ONLINE_FRONT;            // a - b - c
    return ON_SEGMENT;                                    // a - c - b
}

// 2直線の直交判定
bool is_orthogonal(const Line &a, const Line &b) {
    return equals(dot(a.b - a.a, b.b - b.a), 0);
}

// 2直線の平行判定
bool is_parallel(const Line &a, const Line &b) {
    return equals(cross(a.b - a.a, b.b - b.a), 0);
}

// 線分の交差判定
bool is_intersect_ss(const Segment &s, const Segment &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 is_intersect_ll(const Line &l, const Line &m) {
    Real A = cross(l.b - l.a, m.b - m.a);
    Real B = cross(l.b - l.a, l.b - m.a);
    if(equals(abs(A), 0) && equals(abs(B), 0)) return true;
    return !is_parallel(l, m);
}

// 線分に点が乗っているか
bool is_intersect_sp(const Segment &s, const Point &p) {
    return ccw(s.a, s.b, p) == ON_SEGMENT;
}

// 点と点の距離
Real distance_pp(const Point &p1, const Point &p2) {
    return sqrt(pow(real(p1)-real(p2), 2) + pow(imag(p1)-imag(p2), 2));
}

// 点と直線の距離
Real distance_lp(const Line &l, const Point &p) {
    return abs(p - projection(l, p));
}

// 直線と直線の距離
Real distance_ll(const Line &l, const Line &m) {
    return is_intersect_ll(l, m) ? 0 : distance_lp(l, m.a);
}

// 点と線分の距離
Real distance_sp(const Segment &s, const Point &p) {
    Point r = projection(s, p);
    if(is_intersect_sp(s, r)) return abs(r - p);
    return min(abs(s.a - p), abs(s.b - p));
}

// 線分と線分の距離
Real distance_ss(const Segment &a, const Segment &b) {
    if(is_intersect_ss(a, b)) return 0;
    return min({distance_sp(a, b.a), distance_sp(a, b.b), distance_sp(b, a.a), distance_sp(b, a.b)});
}

// 交点
Point cross_point_ll(const Line &l, const Line &m) {
    Real A = cross(l.b - l.a, m.b - m.a);
    Real B = cross(l.b - l.a, l.b - m.a);
    if(equals(abs(A), 0) && equals(abs(B), 0)) return m.a;
    return m.a + (m.b - m.a) * B / A;
}

// 円と円の位置関係
int intersect(Circle c1, Circle c2) {
    if(c1.r < c2.r) swap(c1, c2);
    Real d = abs(c1.p - c2.p);
    if(c1.r + c2.r < d) return 4;
    if(equals(c1.r + c2.r, d)) return 3;
    if(c1.r - c2.r < d) return 2;
    if(equals(c1.r - c2.r, d)) return 1;
    return 0;
}

Real area(const Polygon &p){
    Real A = 0;
    for(int i = 0; i < p.size(); i++){
        A += cross(p[i], p[(i + 1) % p.size()]);
    }
    return A * 0.5;
}

bool is_convex(const Polygon &p){
    for(int i = 0; i < p.size(); i++){
        if(ccw(p[(i + p.size() - 1) % p.size()], p[i], p[(i + 1) % p.size()]) == -1) return false;
    }
    return true;
}

enum { OUT, ON, IN };
int contains(const Polygon &Q, const Point &p){
    bool in = false;
    for(int i = 0; i < Q.size(); i++){
        Point a = Q[i] - p, b = Q[(i + 1) % Q.size()] - p;
        if(a.imag() > b.imag()) swap(a, b);
        if(a.imag() <= 0 && 0 < b.imag() && cross(a, b) < 0) in = !in;
        if(cross(a, b) == 0 && dot(a, b) <= 0) return ON;
    }
    return in ? IN : OUT;
}

Polygon convex_hull(Polygon &p, bool strict = true){
    int n = (int)p.size(), k = 0;
    if(n <= 2) return p;
    sort(p.begin(), p.end());
    Polygon ch(2 * n);
    for(int i = 0; i < n; ch[k++] = p[i++]){
        while(k >= 2 && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
    }
    for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]){
        while(k >= t && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
    }
    ch.resize(k - 1);
    return ch;
}

Real convex_diameter(const Polygon &p){
    int n = (int)p.size();
    int is = 0, js = 0;
    for(int i = 1; i < n; i++){
        if(p[i].imag() > p[is].imag()) is = i;
        if(p[i].imag() < p[js].imag()) js = i;
    }
    Real maxdis = norm(p[is] - p[js]);
    int maxi, maxj, i, j;
    i = maxi = is;
    j = maxj = js;
    do {
        if(cross(p[(i + 1) % n] - p[i], p[(j + 1) % n] - p[j]) >= 0){
            j = (j + 1) % n;
        }else{
            i = (i + 1) % n;
        }

        if(norm(p[i] - p[j]) > maxdis){
            maxdis = norm(p[i] - p[j]);
            maxi = i;
            maxj = j;
        }

    }while(i != is || j != js);
    return sqrt(maxdis);
}

Polygon convex_cut(const Polygon &U, Line l){
    Polygon ret;
    for(int i = 0; i < U.size(); i++){
        Point now = U[i], nxt = U[(i + 1) % U.size()];
        if(ccw(l.a, l.b, now) != -1) ret.push_back(now);
        if(ccw(l.a, l.b, now) * ccw(l.a, l.b, nxt) < 0){
            ret.push_back(cross_point_ll(Line(now, nxt), l));
        }
    }
    return ret;
}

Real ClosetPair(Polygon& ps){
    if(ps.size() <= 1) throw (0);
    sort(begin(ps), end(ps));

    auto compare_y = [&](const Point &a, const Point &b) {
        return a.imag() < b.imag();
    };
    Polygon beet(ps.size());
    const double INF = 1e18;

    function< double(int, int) > rec = [&](int left, int right) {
        if(right - left <= 1) return INF;
        int mid = (left + right) >> 1;
        auto x = ps[mid].real();
        auto ret = min(rec(left, mid), rec(mid, right));
        inplace_merge(begin(ps) + left, begin(ps) + mid, begin(ps) + right, compare_y);
        int ptr = 0;
        for(int i = left; i < right; i++) {
            if(fabs((ps[i].real()) - x) >= ret) continue;
            for(int j = 0; j < ptr; j++) {
                auto luz = ps[i] - beet[ptr - j - 1];
                if(luz.imag() >= ret) break;
                ret = min(ret, abs(luz));
            }
            beet[ptr++] = ps[i];
        }
        return ret;
    };
    return rec(0, (int) ps.size());
}

pair< Point, Point > cross_point_cc(const Circle &c1, const Circle &c2) {
    Real d = abs(c1.p - c2.p);
    Real a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
    Real t = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
    Point p1 = c1.p + Point(cos(t + a) * c1.r, sin(t + a) * c1.r);
    Point p2 = c1.p + Point(cos(t - a) * c1.r, sin(t - a) * c1.r);
    return {p1, p2};
}

const int BOTTOM = 0;
const int LEFT   = 1;
const int RIGHT  = 2;
const int TOP    = 3;

class endPoint {
    public:
        Point p;
        int seg; // id of Point
        int st; // kind of Point
        endPoint(){}
        endPoint(Point inp, int inseg, int inst):p(inp),seg(inseg),st(inst){}
        bool operator<(const endPoint &ep)const {
            if(p.imag() == ep.p.imag()) return st < ep.st;
            else return p.imag() < ep.p.imag();
        }
};

endPoint EP[220000];
int Manhattan_Intersections(vector< Segment > s){
    int n = s.size();
    double hoge;

    for(int i = 0, k = 0; i < n; i++){
        if(s[i].a.imag() == s[i].b.imag()){
            if(s[i].a.real() > s[i].b.real()){
                hoge = s[i].a.real();
                s[i].a.real(s[i].b.real());
                s[i].b.real(hoge);
            }
        }else if(s[i].a.imag() > s[i].b.imag()){
            hoge = s[i].a.imag();
            s[i].a.imag(s[i].b.imag());
            s[i].b.imag(hoge);
        }

        if(s[i].a.imag() == s[i].b.imag()){
            EP[k++] = endPoint(s[i].a, i, LEFT);
            EP[k++] = endPoint(s[i].b, i, RIGHT);
        }else{
            EP[k++] = endPoint(s[i].a, i, BOTTOM);
            EP[k++] = endPoint(s[i].b, i, TOP);
        }
    }

    sort(EP, EP + 2 * n);
    set<int> BT;
    BT.insert(1000000001);
    int cnt = 0;
    for(int i = 0; i < 2 * n; i++){
        if(EP[i].st == TOP) BT.erase(EP[i].p.real());
        else if(EP[i].st == BOTTOM) BT.insert(EP[i].p.real());
        else if(EP[i].st == LEFT){
            set<int>::iterator b = lower_bound(BT.begin(), BT.end(), s[EP[i].seg].a.real());
            set<int>::iterator e = upper_bound(BT.begin(), BT.end(), s[EP[i].seg].b.real());
            cnt += distance(b, e);
        }
    }

    return cnt;
}

// 内接円
Circle Inscribed_Circle(const Point& a, const Point& b, const Point& c){
    double A = abs(b - c), B = abs(c - a), C = abs(a - b);
    Point x = Point((a * A + b * B + c * C) / (A + B + C));
    double r = distance_sp(Segment(a,b),x);
    return Circle(x, r);
}

// 外接円
Circle Circumscribed_Circle(const Point& a, const Point& b, const Point& c){
    Point m1((a+b)/2.0), m2((b+c)/2.0);
    Point v((b-a).imag(), (a-b).real()), w((b-c).imag(), (c-b).real());
    Line s(m1, Point(m1+v)), t(m2, Point(m2+w));
    const Point x = cross_point_ll(s, t);
    return Circle(x, abs(a-x));
}

pair< Point, Point > cross_point_cl(const Circle &c, const Line &l) {
    Point pr = projection(l, c.p);
    if(equals(abs(pr - c.p), c.r)) return {pr, pr};
    Point e = (l.b - l.a) / abs(l.b - l.a);
    auto k = sqrt(norm(c.r) - norm(pr - c.p));
    return {pr - e * k, pr + e * k};
}

// 点pを通る円の接線
pair<Point,Point> tangent_cp(const Circle &c, const Point &p) {
    return cross_point_cc(c, Circle(p, sqrt(norm(c.p - p) - c.r * c.r)));
}

// 二つの円の共通接線
vector< Line > tangent_cc(Circle c1, Circle c2){
    vector< Line > ret;
    if(c1.r < c2.r) swap(c1,c2);
    double g = norm(c1.p-c2.p);
    if(equals(g,0.0)) return ret;
    Point u = (c2.p-c1.p)/sqrt(g);
    Point v = rotate(u, PI * 0.5);
    for(int s:{-1,1}){
        double h = (c1.r+ s*c2.r)/sqrt(g);
        if(equals(1- h*h, 0)){
            ret.emplace_back(c1.p+u*c1.r, c1.p+(u+v)*c1.r);
        }else if(1-h*h > 0){
            Point uu = u*h, vv = v*sqrt(1-h*h);
            ret.emplace_back(c1.p+(uu+vv)*c1.r, c2.p-(uu+vv)*c2.r*s);
            ret.emplace_back(c1.p+(uu-vv)*c1.r, c2.p-(uu-vv)*c2.r*s);
        }
    }
    return ret;
}

Real area_poly_c(const Polygon &p, const Circle &c) {
    if(p.size() < 3) return 0.0;
    function< Real(Circle, Point, Point) > cross_area = [&](const Circle &c, const Point &a, const Point &b) {
        Point va = c.p - a, vb = c.p - b;
        Real f = cross(va, vb), ret = 0.0;
        if(equals(f, 0.0)) return ret;
        if(max(abs(va), abs(vb)) < c.r + EPS) return f;
        if(distance_sp(Segment(a, b), c.p) > c.r - EPS) return c.r * c.r * arg(vb * conj(va));
        auto u = cross_point_cl(c, Segment(a, b));
        vector< Point > tot{a, u.first, u.second, b};
        for(int i = 0; i + 1 < tot.size(); i++) {
            ret += cross_area(c, tot[i], tot[i + 1]);
        }
        return ret;
    };
    Real A = 0;
    for(int i = 0; i < p.size(); i++) {
        A += cross_area(c, p[i], p[(i + 1) % p.size()]);
    }
    return A;
}

Real area_cc(const Circle &c1, const Circle &c2) {
    Real d = abs(c1.p - c2.p);
    if(c1.r + c2.r <= d + EPS) return 0.0;
    if(d <= fabs(c1.r - c2.r) + EPS) {
        Real r = min(c1.r, c2.r);
        return r * r * PI;
    }
    Real rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
    Real theta = acos(rc / c1.r);
    Real phi = acos((d - rc) / c2.r);
    return (c1.r * c1.r*theta + c2.r*c2.r*phi - d*c1.r*sin(theta));
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(0);

    while(true) {
        int n; cin >> n; if(n == 0) break;
        Polygon p(n);
        rep(i,n) cin >> p[i];
        Real tg,tw; cin >> tg >> tw;
        Point s,t; cin >> s >> t;

        auto f = [&](Segment l, Point q) {
            Point lo = l.a, hi = l.b;
            rep(_,50) {
                Point m1 = (lo + lo + hi) / 3.0;
                Point m2 = (lo + hi + hi) / 3.0;
                auto get = [&](Point x) { return abs(x - l.a) * tg + abs(x - q) * tw; };
                if(get(m1) > get(m2)) lo = m1; else hi = m2;
            }
            return lo;
        };

        vector< Point > v; v.push_back(s); v.push_back(t);
        rep(i,n)rep(j,n) if(i != j) {
            v.push_back(f(Segment(p[i], p[(i + 1) % n]), p[j]));
            v.push_back(f(Segment(p[(i + 1) % n], p[i]), p[j]));
        }

        rep(i,n) {
            v.push_back(f(Segment(p[i], p[(i + 1) % n]), s));
            v.push_back(f(Segment(p[i], p[(i + 1) % n]), t));
            v.push_back(f(Segment(p[(i + 1) % n], p[i]), s));
            v.push_back(f(Segment(p[(i + 1) % n], p[i]), t));
        }

        int M = v.size();
        vector<vector< Real >> d(M, vector< Real >(M, 1e9));
        rep(i,M)rep(j,M) {
            d[i][j] = d[j][i] = abs(v[i] - v[j]) * tw;
            rep(k,n) {
                if(is_intersect_sp(Segment(p[k], p[(k + 1) % n]), v[i])
                && is_intersect_sp(Segment(p[k], p[(k + 1) % n]), v[j]))
                        d[i][j] = d[j][i] = min(d[i][j], abs(v[i] - v[j]) * tg);
            }
        }
        
        rep(k,M)rep(i,M)rep(j,M) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
        cout.precision(17);
        cout << d[0][1] << endl;
    }
}
accuracy: 1
time_ms: 2280
memory_kb: 9100
final_rank: 18

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

const double EPS = 1e-10;
const double INF = 1e12;
#define X real()
#define Y imag()
#define EQ(n,m) (abs((n)-(m)) < EPS)
typedef complex<double> P;
typedef vector<P> VP;
namespace std{
    bool operator < (const P& a, const P& b){
        return (a.X!=b.X) ? a.X<b.X : a.Y<b.Y;
    }
}
bool ItsSP(P a, P b, P c){
    return (abs(a-c) +abs(b-c) -abs(b-a)) < EPS;
}
void tri_search(P a, P b, P c, P d, double tg, double tw, VP &ret){
    for(int i=0; i<2; i++){
        P v[4] = {a,b,c,d};
        if(i==0) reverse(v, v+4);
        for(int j=0; j<2; j++){
            P g = v[2+j];
            P beg=v[0], end=v[1];
            for(int rep=0; rep<50; rep++){
                P dir = end-beg;
                P mid1 = beg +dir*(1.0/3);
                P mid2 = beg +dir*(2.0/3);
                if(tg*abs(mid1-v[0]) +tw*abs(g-mid1) > tg*abs(mid2-v[0]) +tw*abs(g-mid2)){
                    beg = mid1;
                }else{
                    end = mid2;
                }
            }
            ret.push_back(beg);
        }
    }
}

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

        VP v, poly;
        v.reserve(400);
        for(int i=0; i<n; i++){
            int x,y;
            cin >> x >> y;
            v.push_back(P(x,y));
            poly.push_back(P(x,y));
        }

        int tg,tw, sx,sy, gx,gy;
        cin >> tg >> tw;
        cin >> sx >> sy >> gx >> gy;
        P s(sx,sy), g(gx,gy);

        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                tri_search(v[i], v[(i+1)%n], v[j], v[(j+1)%n], tg, tw, v);
                tri_search(v[(i+1)%n], v[i], v[(j+1)%n], v[j], tg, tw, v);
            }
            tri_search(v[i], v[(i+1)%n], s, s, tg, tw, v);
            tri_search(v[(i+1)%n], v[i], s, s, tg, tw, v);
            tri_search(v[i], v[(i+1)%n], g, g, tg, tw, v);
            tri_search(v[(i+1)%n], v[i], g, g, tg, tw, v);
        }

        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        v.push_back(s);
        v.push_back(g);
        int sv = v.size();
        vector<vector<double> > adj(sv, vector<double>(sv, INF));
        for(int i=0; i<sv; i++){
            for(int j=i+1; j<sv; j++){
                bool onedge = false;
                for(int e=0; e<n; e++){
                    if(ItsSP(poly[e], poly[(e+1)%n], v[i]) && ItsSP(poly[e], poly[(e+1)%n], v[j])){
                        onedge = true;
                        break;
                    }
                }
                if(onedge){
                    adj[i][j] = adj[j][i] = tg *abs(v[i]-v[j]);
                }else{
                    adj[i][j] = adj[j][i] = tw *abs(v[i]-v[j]);
                }
            }
        }    

        double ans = INF;
        priority_queue<pair<double, int> > wait;
        vector<double> mincost(sv, INF);
        wait.push(make_pair(0,sv-2));
        mincost[sv-2] = 0;
        while(!wait.empty()){
            int p = wait.top().second;
            double cost = -wait.top().first;
            wait.pop();
            if(cost > mincost[p]) continue;
            if(p == sv-1){
                ans = cost;
                break;
            }
            for(int i=0; i<sv; i++){
                double newcost = cost+adj[p][i];
                if(newcost < mincost[i]){
                    wait.push(make_pair(-newcost, i));
                    mincost[i] = newcost;
                }
            }
        }   

        cout << fixed;
        cout << setprecision(12);
        cout << ans << string(1000, '0') << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 550
memory_kb: 3248
final_rank: 14

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 12

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	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); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return 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;
	}

   	/*
	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}*/

	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};

struct Data{

	int p[2];
};

struct State{

	State(int arg_node_id,double arg_sum_dist){
		node_id = arg_node_id;
		sum_dist = arg_sum_dist;
	}

	int node_id;
	double sum_dist;
};

int N;
double TG,TW;
double min_dist[SIZE][SIZE];
Point start,goal;
Data line[SIZE];



double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

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

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

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

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

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector 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(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

Point calc_Reflection_Point(double x1,double y1,double x2,double y2,double xp,double yp){

	Point ret;

	bool X_FLG = false,Y_FLG = false;
	double slope;

	if(y1 == y2){
		X_FLG = true;
	}else if(x1 == x2){
		Y_FLG = true;
	}else{
		slope = (y2-y1)/(x2-x1);
	}

	if(X_FLG){
		ret.x = xp,ret.y=y1;
	}else if(Y_FLG){
		ret.x = x1,ret.y = yp;
	}else{
		ret.x = (yp*(x2-x1)*(y2-y1)+xp*(x2-x1)*(x2-x1)-y1*(y2-y1)*(x2-x1)+x1*(y2-y1)*(y2-y1))/((y2-y1)*(y2-y1)+(x2-x1)*(x2-x1));
		ret.y = ((x1-x2)*ret.x+yp*(y2-y1)+xp*(x2-x1))/(y2-y1);
	}
	ret.x = 2*ret.x-xp;
	ret.y = 2*ret.y-yp;

	return ret;
}

Point calc_Reflection_Point(Line line,Point point){

	return calc_Reflection_Point(line.p[0].x,line.p[0].y,line.p[1].x,line.p[1].y,point.x,point.y);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//切片を求める関数
double calc_add(Line line){

	double slope = calc_slope(line);

	if(fabs(slope-DBL_MAX) < EPS){

		return DBL_MAX;

	}else if(fabs(slope) < EPS){

		return line.p[0].y;

	}else{

		return line.p[0].y-slope*line.p[0].x;
	}
}

//線分のx座標を指定した時の座標を求める
Point calc_pos(Line line,double x){

	Point ret;

	double slope = calc_slope(line);
	if(fabs(slope-DBL_MAX) < EPS){

		ret = Point(DBL_MAX,DBL_MAX);
		return ret;
	}

	double add = calc_add(line);

	if(fabs(slope) < EPS){

		ret = Point(x,add);

	}else{

		ret = Point(x,slope*x+add);
	}

	return ret;
}


void func(){

	Polygon first_P;

	double x,y;
	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&x,&y);
		first_P.push_back(Point(x,y));
	}

	scanf("%lf %lf",&TG,&TW);
	scanf("%lf %lf",&start.x,&start.y);
	scanf("%lf %lf",&goal.x,&goal.y);

	Polygon P;

	bool FLG = false;
	for(int i = 0; i < N; i++){
		if(first_P[i] == start){
			FLG = true;
			break;
		}
	}

	if(FLG){ //startが端点

		P = first_P;
	}else{

		P.push_back(first_P[0]);

		for(int i = 1; i <= N; i++){
			Line tmp_line = Line(first_P[i-1],first_P[i%N]);
			if(getDistanceSP(tmp_line,start) < EPS){

				P.push_back(start);
			}
			if(i == N)break;
			P.push_back(first_P[i]);
		}

		N++;
	}

	int num_line = 0;
	for(int i = 0; i < N; i++){

		line[num_line].p[0] = i;
		line[num_line++].p[1] = (i+1)%N;
	}

	//starのindexを求める
	int start_index = -1;
	for(int i = 0; i < N; i++){

		if(P[i] == start){

			start_index = i;
			break;
		}
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(i != k){
				min_dist[i][k] = BIG_NUM;
			}else{
				min_dist[i][k] = 0;
			}
		}
	}

	//隣接する点間にエッジを張る
	for(int i = 0; i < num_line; i++){
		int a = line[i].p[0];
		int b = line[i].p[1];

		double tmp_dist = calc_dist(P[a],P[b])*TG;

		min_dist[a][b] = min(min_dist[a][b],tmp_dist);
		min_dist[b][a] = min(min_dist[b][a],tmp_dist);
	}


	//スタートから直後に飛び込んで,水中から入次し、かつ線分の端まで行く場合のコスト
	for(int i = 0; i < num_line; i++){
		if(line[i].p[0] == start_index || line[i].p[1] == start_index)continue;

		Line tmp_line = Line(P[line[i].p[0]],P[line[i].p[1]]);
		Point tmp_p = calc_Reflection_Point(tmp_line,start);
		Line work_line = Line(start,tmp_p);

		if(!is_Cross(tmp_line,work_line))continue;

		Point cross_p = calc_Cross_Point(tmp_line,work_line);

		double A = calc_dist(start,cross_p);
		double x = (A*TG)/(sqrt(TW*TW-TG*TG));

		double len_0 = calc_dist(cross_p,P[line[i].p[0]]);

		if(x <= len_0){
			double dist_0 = sqrt(A*A+x*x)*TW+(len_0-x)*TG;
			min_dist[start_index][line[i].p[0]] = min(min_dist[start_index][line[i].p[0]],dist_0);
			min_dist[line[i].p[0]][start_index] = min(min_dist[line[i].p[0]][start_index],dist_0);
		}

		double len_1 = calc_dist(cross_p,P[line[i].p[1]]);

		if(x <= len_1){
			double dist_1 = sqrt(A*A+x*x)*TW+(len_1-x)*TG;

			min_dist[start_index][line[i].p[1]] = min(min_dist[start_index][line[i].p[1]],dist_1);
			min_dist[line[i].p[1]][start_index] = min(min_dist[line[i].p[1]][start_index],dist_1);
		}
	}

	double ans = calc_dist(start,goal)*TW; //水中を直進

	for(int mid = 0; mid < N; mid++){
		for(int st = 0; st < N; st++){
			if(fabs(min_dist[st][mid]-BIG_NUM) < EPS)continue;
			for(int gl = 0; gl < N; gl++){
				if(fabs(min_dist[mid][gl]-BIG_NUM) < EPS)continue;

				min_dist[st][gl] = min(min_dist[st][gl],min_dist[st][mid]+min_dist[mid][gl]);
			}
		}
	}

	double L,R;
	double tmp_ans;
	Point work1,work2;

	//辺の途中に水中からの入次はなく、辺の途中で水中に飛び込む場合
	for(int i = 0; i < num_line; i++){

		int a = line[i].p[0];
		int b = line[i].p[1];

		Line tmp_line = Line(P[a],P[b]);

		double slope = calc_slope(tmp_line);
		tmp_ans = BIG_NUM;

		for(int loop = 0; loop < 2; loop++){

			if(fabs(slope-DBL_MAX) < EPS){ //垂直

				L = min(P[a].y,P[b].y);
				R = max(P[a].y,P[b].y);

				double X = P[a].x;

				for(int loop = 0; loop < 100; loop++){

					double mid1 = (2.0*L+R)/3.0;
					work1 = Point(X,mid1);

					double mid2 = (1.0*L+2.0*R)/3.0;
					work2 = Point(X,mid2);

					double t1 = calc_dist(P[a],work1)*TG+calc_dist(work1,goal)*TW;
					double t2 = calc_dist(P[a],work2)*TG+calc_dist(work2,goal)*TW;
					tmp_ans = min(tmp_ans,min_dist[start_index][a]+min(t1,t2));

					if(t1 <= t2){

						R = mid2;

					}else{

						L = mid1;
					}
				}

				ans = min(ans,tmp_ans);

			}else{ //その他

				L = min(P[a].x,P[b].x);
				R = max(P[a].x,P[b].x);

				for(int loop = 0; loop < 100; loop++){

					double mid1 = (2.0*L+R)/3.0;
					work1 = calc_pos(tmp_line,mid1);

					double mid2 = (1.0*L+2.0*R)/3.0;
					work2 = calc_pos(tmp_line,mid2);

					double t1 = calc_dist(P[a],work1)*TG+calc_dist(work1,goal)*TW;
					double t2 = calc_dist(P[a],work2)*TG+calc_dist(work2,goal)*TW;
					tmp_ans = min(tmp_ans,min_dist[start_index][a]+min(t1,t2));

					if(t1 <= t2){

						R = mid2;

					}else{

						L = mid1;
					}
				}

				ans = min(ans,tmp_ans);
			}
			swap(a,b);
		}
	}

	//水中から入次する辺と飛び込む辺が同じ場合
	for(int i = 0; i < num_line; i++){
		if(line[i].p[0] == start_index || line[i].p[1] == start_index)continue;

		Line tmp_line = Line(P[line[i].p[0]],P[line[i].p[1]]);
		Point tmp_p = calc_Reflection_Point(tmp_line,start);
		Line work_line = Line(start,tmp_p);

		if(!is_Cross(tmp_line,work_line))continue;

		Point cross_p = calc_Cross_Point(tmp_line,work_line);

		int a = line[i].p[0];
		int b = line[i].p[1];

		double A = calc_dist(start,cross_p);
		double x = (A*TG)/(sqrt(TW*TW-TG*TG));

		double slope = calc_slope(tmp_line);
		double tmp_ans = BIG_NUM;

		for(int loop = 0; loop < 2; loop++){

			if(fabs(slope-DBL_MAX) < EPS){ //垂直

				L = min(P[a].y,cross_p.y);
				R = max(P[a].y,cross_p.y);

				double X = P[a].x;

				for(int loop = 0; loop < 100; loop++){

					double mid1 = (2.0*L+R)/3.0;
					work1 = Point(X,mid1);

					double mid2 = (1.0*L+2.0*R)/3.0;
					work2 = Point(X,mid2);

					double t1,t2;
					if(calc_dist(cross_p,work1)+EPS < x){

						t1 = BIG_NUM;
					}else{

						t1 = sqrt(A*A+x*x)*TW+((calc_dist(work1,cross_p)-x))*TG+calc_dist(work1,goal)*TW;
					}
					if(calc_dist(cross_p,work2)+EPS < x){

						t2 = BIG_NUM;
					}else{

						t2 = sqrt(A*A+x*x)*TW+((calc_dist(work2,cross_p)-x))*TG+calc_dist(work2,goal)*TW;
					}

					tmp_ans = min(tmp_ans,min(t1,t2));

					if(t1 <= t2){

						R = mid2;

					}else{

						L = mid1;
					}
				}

				ans = min(ans,tmp_ans);

			}else{

				L = min(P[a].x,cross_p.x);
				R = max(P[a].x,cross_p.x);

				for(int loop = 0; loop < 100; loop++){

					double mid1 = (2.0*L+R)/3.0;
					work1 = calc_pos(tmp_line,mid1);

					double mid2 = (1.0*L+2.0*R)/3.0;
					work2 = calc_pos(tmp_line,mid2);

					double t1,t2;
					if(calc_dist(cross_p,work1)+EPS < x){

						t1 = BIG_NUM;
					}else{

						t1 = sqrt(A*A+x*x)*TW+((calc_dist(work1,cross_p)-x))*TG+calc_dist(work1,goal)*TW;
					}
					if(calc_dist(cross_p,work2)+EPS < x){

						t2 = BIG_NUM;
					}else{

						t2 = sqrt(A*A+x*x)*TW+((calc_dist(work2,cross_p)-x))*TG+calc_dist(work2,goal)*TW;
					}

					tmp_ans = min(tmp_ans,min(t1,t2));

					if(t1 <= t2){

						R = mid2;

					}else{

						L = mid1;
					}
				}

				ans = min(ans,tmp_ans);

			}
			swap(a,b);
		}
	}

	printf("%.12lf\n",ans);

}


int main(){

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3216
final_rank: 9

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 12

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	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); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return 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;
	}

   	/*
	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}*/

	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};

struct Data{

	int p[2];
};

struct State{

	State(int arg_node_id,double arg_sum_dist){
		node_id = arg_node_id;
		sum_dist = arg_sum_dist;
	}

	int node_id;
	double sum_dist;
};

int N;
double TG,TW;
double min_dist[SIZE][SIZE];
Point start,goal;
Data line[SIZE];



double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

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

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

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

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

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector 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(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

Point calc_Reflection_Point(double x1,double y1,double x2,double y2,double xp,double yp){

	Point ret;

	bool X_FLG = false,Y_FLG = false;
	double slope;

	if(y1 == y2){
		X_FLG = true;
	}else if(x1 == x2){
		Y_FLG = true;
	}else{
		slope = (y2-y1)/(x2-x1);
	}

	if(X_FLG){
		ret.x = xp,ret.y=y1;
	}else if(Y_FLG){
		ret.x = x1,ret.y = yp;
	}else{
		ret.x = (yp*(x2-x1)*(y2-y1)+xp*(x2-x1)*(x2-x1)-y1*(y2-y1)*(x2-x1)+x1*(y2-y1)*(y2-y1))/((y2-y1)*(y2-y1)+(x2-x1)*(x2-x1));
		ret.y = ((x1-x2)*ret.x+yp*(y2-y1)+xp*(x2-x1))/(y2-y1);
	}
	ret.x = 2*ret.x-xp;
	ret.y = 2*ret.y-yp;

	return ret;
}

Point calc_Reflection_Point(Line line,Point point){

	return calc_Reflection_Point(line.p[0].x,line.p[0].y,line.p[1].x,line.p[1].y,point.x,point.y);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//切片を求める関数
double calc_add(Line line){

	double slope = calc_slope(line);

	if(fabs(slope-DBL_MAX) < EPS){

		return DBL_MAX;

	}else if(fabs(slope) < EPS){

		return line.p[0].y;

	}else{

		return line.p[0].y-slope*line.p[0].x;
	}
}

//線分のx座標を指定した時の座標を求める
Point calc_pos(Line line,double x){

	Point ret;

	double slope = calc_slope(line);
	if(fabs(slope-DBL_MAX) < EPS){

		ret = Point(DBL_MAX,DBL_MAX);
		return ret;
	}

	double add = calc_add(line);

	if(fabs(slope) < EPS){

		ret = Point(x,add);

	}else{

		ret = Point(x,slope*x+add);
	}

	return ret;
}


void func(){

	Polygon first_P;

	double x,y;
	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&x,&y);
		first_P.push_back(Point(x,y));
	}

	scanf("%lf %lf",&TG,&TW);
	scanf("%lf %lf",&start.x,&start.y);
	scanf("%lf %lf",&goal.x,&goal.y);

	Polygon P;

	bool FLG = false;
	for(int i = 0; i < N; i++){
		if(first_P[i] == start){
			FLG = true;
			break;
		}
	}

	if(FLG){ //startが端点

		//printf("startは点\n");

		P = first_P;
	}else{

		P.push_back(first_P[0]);

		for(int i = 1; i <= N; i++){
			Line tmp_line = Line(first_P[i-1],first_P[i%N]);
			if(getDistanceSP(tmp_line,start) < EPS){

				P.push_back(start);
			}
			if(i == N)break;
			P.push_back(first_P[i]);
		}

		N++;
	}

	int num_line = 0;
	for(int i = 0; i < N; i++){

		line[num_line].p[0] = i;
		line[num_line++].p[1] = (i+1)%N;
	}

	//starのindexを求める
	int start_index = -1;
	for(int i = 0; i < N; i++){

		if(P[i] == start){

			start_index = i;
			break;
		}
	}

	//printf("start_index:%d\n",start_index);

	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(i != k){
				min_dist[i][k] = BIG_NUM;
			}else{
				min_dist[i][k] = 0;
			}
		}
	}

	//隣接する点間にエッジを張る
	for(int i = 0; i < num_line; i++){
		int a = line[i].p[0];
		int b = line[i].p[1];

		double tmp_dist = calc_dist(P[a],P[b])*TG;

		min_dist[a][b] = min(min_dist[a][b],tmp_dist);
		min_dist[b][a] = min(min_dist[b][a],tmp_dist);
	}


	//スタートから直後に飛び込んで,水中から入次し、かつ線分の端まで行く場合のコスト
	for(int i = 0; i < num_line; i++){
		if(line[i].p[0] == start_index || line[i].p[1] == start_index)continue;

		Line tmp_line = Line(P[line[i].p[0]],P[line[i].p[1]]);
		Point tmp_p = calc_Reflection_Point(tmp_line,start);
		Line work_line = Line(start,tmp_p);

		if(!is_Cross(tmp_line,work_line))continue;

		Point cross_p = calc_Cross_Point(tmp_line,work_line);

		double A = calc_dist(start,cross_p);
		double x = (A*TG)/(sqrt(TW*TW-TG*TG));

		double len_0 = calc_dist(cross_p,P[line[i].p[0]]);

		if(x <= len_0){
			double dist_0 = sqrt(A*A+x*x)*TW+(len_0-x)*TG;
			min_dist[start_index][line[i].p[0]] = min(min_dist[start_index][line[i].p[0]],dist_0);
			min_dist[line[i].p[0]][start_index] = min(min_dist[line[i].p[0]][start_index],dist_0);
		}

		double len_1 = calc_dist(cross_p,P[line[i].p[1]]);

		if(x <= len_1){
			double dist_1 = sqrt(A*A+x*x)*TW+(len_1-x)*TG;

			min_dist[start_index][line[i].p[1]] = min(min_dist[start_index][line[i].p[1]],dist_1);
			min_dist[line[i].p[1]][start_index] = min(min_dist[line[i].p[1]][start_index],dist_1);
		}
	}

	double ans = calc_dist(start,goal)*TW; //水中を直進

	//printf("最初のans:%.5lf\n",ans);

	for(int mid = 0; mid < N; mid++){
		for(int st = 0; st < N; st++){
			if(fabs(min_dist[st][mid]-BIG_NUM) < EPS)continue;
			for(int gl = 0; gl < N; gl++){
				if(fabs(min_dist[mid][gl]-BIG_NUM) < EPS)continue;

				min_dist[st][gl] = min(min_dist[st][gl],min_dist[st][mid]+min_dist[mid][gl]);
			}
		}
	}

	/*for(int i = 0; i < N; i++){
		if(i == start_index){

			printf("start\n");
		}
		printf("min_dist[%d]:%.5lf\n",i,min_dist[start_index][i]);

	}*/
	double L,R;
	double tmp_ans;
	Point work1,work2;

	//辺の途中に水中からの入次はなく、辺の途中で水中に飛び込む場合
	for(int i = 0; i < num_line; i++){

		int a = line[i].p[0];
		int b = line[i].p[1];

		//printf("a:%d b:%d\n",a,b);

		Line tmp_line = Line(P[a],P[b]);

		double slope = calc_slope(tmp_line);
		tmp_ans = BIG_NUM;

		for(int loop = 0; loop < 2; loop++){

			//if(min_dist[start_index][a] >= ans)continue;

			if(fabs(slope-DBL_MAX) < EPS){ //垂直

				L = min(P[a].y,P[b].y);
				R = max(P[a].y,P[b].y);

				double X = P[a].x;

				for(int loop = 0; loop < 100; loop++){

					double mid1 = (2.0*L+R)/3.0;
					work1 = Point(X,mid1);

					double mid2 = (1.0*L+2.0*R)/3.0;
					work2 = Point(X,mid2);

					double t1 = calc_dist(P[a],work1)*TG+calc_dist(work1,goal)*TW;
					double t2 = calc_dist(P[a],work2)*TG+calc_dist(work2,goal)*TW;
					tmp_ans = min(tmp_ans,min_dist[start_index][a]+min(t1,t2));

					if(t1 <= t2){

						R = mid2;

					}else{

						L = mid1;
					}
				}

				ans = min(ans,tmp_ans);

			}else{ //その他

				L = min(P[a].x,P[b].x);
				R = max(P[a].x,P[b].x);

				for(int loop = 0; loop < 100; loop++){

					double mid1 = (2.0*L+R)/3.0;
					work1 = calc_pos(tmp_line,mid1);

					double mid2 = (1.0*L+2.0*R)/3.0;
					work2 = calc_pos(tmp_line,mid2);

					double t1 = calc_dist(P[a],work1)*TG+calc_dist(work1,goal)*TW;
					double t2 = calc_dist(P[a],work2)*TG+calc_dist(work2,goal)*TW;
					tmp_ans = min(tmp_ans,min_dist[start_index][a]+min(t1,t2));

					if(t1 <= t2){

						R = mid2;

					}else{

						L = mid1;
					}
				}

				ans = min(ans,tmp_ans);
			}
			swap(a,b);
		}
	}

	//printf("ans2:%.12lf\n",ans);

	//水中から入次する辺と飛び込む辺が同じ場合
	for(int i = 0; i < num_line; i++){
		if(line[i].p[0] == start_index || line[i].p[1] == start_index)continue;

		Line tmp_line = Line(P[line[i].p[0]],P[line[i].p[1]]);
		Point tmp_p = calc_Reflection_Point(tmp_line,start);
		Line work_line = Line(start,tmp_p);

		if(!is_Cross(tmp_line,work_line))continue;

		Point cross_p = calc_Cross_Point(tmp_line,work_line);

		int a = line[i].p[0];
		int b = line[i].p[1];

		double A = calc_dist(start,cross_p);
		double x = (A*TG)/(sqrt(TW*TW-TG*TG));

		double slope = calc_slope(tmp_line);
		double tmp_ans = BIG_NUM;

		for(int loop = 0; loop < 2; loop++){

			if(fabs(slope-DBL_MAX) < EPS){ //垂直

				L = min(P[a].y,cross_p.y);
				R = max(P[a].y,cross_p.y);

				double X = P[a].x;

				for(int loop = 0; loop < 100; loop++){

					double mid1 = (2.0*L+R)/3.0;
					work1 = Point(X,mid1);

					double mid2 = (1.0*L+2.0*R)/3.0;
					work2 = Point(X,mid2);

					double t1,t2;
					if(calc_dist(cross_p,work1)+EPS < x){

						t1 = BIG_NUM;
					}else{

						t1 = sqrt(A*A+x*x)*TW+((calc_dist(work1,cross_p)-x))*TG+calc_dist(work1,goal)*TW;
					}
					if(calc_dist(cross_p,work2)+EPS < x){

						t2 = BIG_NUM;
					}else{

						t2 = sqrt(A*A+x*x)*TW+((calc_dist(work2,cross_p)-x))*TG+calc_dist(work2,goal)*TW;
					}

					tmp_ans = min(tmp_ans,min(t1,t2));

					if(t1 <= t2){

						R = mid2;

					}else{

						L = mid1;
					}
				}

				ans = min(ans,tmp_ans);

			}else{

				L = min(P[a].x,cross_p.x);
				R = max(P[a].x,cross_p.x);

				for(int loop = 0; loop < 100; loop++){

					double mid1 = (2.0*L+R)/3.0;
					work1 = calc_pos(tmp_line,mid1);

					double mid2 = (1.0*L+2.0*R)/3.0;
					work2 = calc_pos(tmp_line,mid2);

					double t1,t2;
					if(calc_dist(cross_p,work1)+EPS < x){

						t1 = BIG_NUM;
					}else{

						t1 = sqrt(A*A+x*x)*TW+((calc_dist(work1,cross_p)-x))*TG+calc_dist(work1,goal)*TW;
					}
					if(calc_dist(cross_p,work2)+EPS < x){

						t2 = BIG_NUM;
					}else{

						t2 = sqrt(A*A+x*x)*TW+((calc_dist(work2,cross_p)-x))*TG+calc_dist(work2,goal)*TW;
					}

					tmp_ans = min(tmp_ans,min(t1,t2));

					if(t1 <= t2){

						R = mid2;

					}else{

						L = mid1;
					}
				}

				ans = min(ans,tmp_ans);

			}
			swap(a,b);
		}
	}

	printf("%.12lf\n",ans);

}


int main(){

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3288
final_rank: 11

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

const double EPS = 1e-10;
const double INF = 1e12;
#define X real()
#define Y imag()
#define EQ(n,m) (abs((n)-(m)) < EPS)
typedef complex<double> P;
typedef vector<P> VP;
namespace std{
    bool operator < (const P& a, const P& b){
        return (a.X!=b.X) ? a.X<b.X : a.Y<b.Y;
    }
}
bool ItsSP(P a, P b, P c){
    return (abs(a-c) +abs(b-c) -abs(b-a)) < EPS;
}
void tri_search(P a, P b, P c, P d, double tg, double tw, VP &ret){
    for(int i=0; i<2; i++){
        P v[4] = {a,b,c,d};
        if(i==0) reverse(v, v+4);
        for(int j=0; j<2; j++){
            P g = v[2+j];
            P beg=v[0], end=v[1];
            for(int rep=0; rep<50; rep++){
                P dir = end-beg;
                P mid1 = beg +dir*(1.0/3);
                P mid2 = beg +dir*(2.0/3);
                if(tg*abs(mid1-v[0]) +tw*abs(g-mid1) > tg*abs(mid2-v[0]) +tw*abs(g-mid2)){
                    beg = mid1;
                }else{
                    end = mid2;
                }
            }
            ret.push_back(beg);
        }
    }
}

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

        VP v, poly;
        v.reserve(400);
        for(int i=0; i<n; i++){
            int x,y;
            cin >> x >> y;
            v.push_back(P(x,y));
            poly.push_back(P(x,y));
        }

        int tg,tw, sx,sy, gx,gy;
        cin >> tg >> tw;
        cin >> sx >> sy >> gx >> gy;
        P s(sx,sy), g(gx,gy);

        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                tri_search(v[i], v[(i+1)%n], v[j], v[(j+1)%n], tg, tw, v);
                tri_search(v[(i+1)%n], v[i], v[(j+1)%n], v[j], tg, tw, v);
            }
            tri_search(v[i], v[(i+1)%n], s, s, tg, tw, v);
            tri_search(v[(i+1)%n], v[i], s, s, tg, tw, v);
            tri_search(v[i], v[(i+1)%n], g, g, tg, tw, v);
            tri_search(v[(i+1)%n], v[i], g, g, tg, tw, v);
        }

        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        v.push_back(s);
        v.push_back(g);
        int sv = v.size();
        vector<vector<double> > adj(sv, vector<double>(sv, INF));
        for(int i=0; i<sv; i++){
            for(int j=i+1; j<sv; j++){
                bool onedge = false;
                for(int e=0; e<n; e++){
                    if(ItsSP(poly[e], poly[(e+1)%n], v[i]) && ItsSP(poly[e], poly[(e+1)%n], v[j])){
                        onedge = true;
                        break;
                    }
                }
                if(onedge){
                    adj[i][j] = adj[j][i] = tg *abs(v[i]-v[j]);
                }else{
                    adj[i][j] = adj[j][i] = tw *abs(v[i]-v[j]);
                }
            }
        }    

        double ans = INF;
        priority_queue<pair<double, int> > wait;
        vector<double> mincost(sv, INF);
        wait.push(make_pair(0,sv-2));
        mincost[sv-2] = 0;
        while(!wait.empty()){
            int p = wait.top().second;
            double cost = -wait.top().first;
            wait.pop();
            if(cost > mincost[p]) continue;
            if(p == sv-1){
                ans = cost;
                break;
            }
            for(int i=0; i<sv; i++){
                double newcost = cost+adj[p][i];
                if(newcost < mincost[i]){
                    wait.push(make_pair(-newcost, i));
                    mincost[i] = newcost;
                }
            }
        }   

        cout << fixed;
        cout << setprecision(12);
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 550
memory_kb: 3380
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
  
typedef long double ldouble;
const ldouble eps = 0.000000001;
bool eq(ldouble a,ldouble b){return (-eps<a-b && a-b<eps);}
 
struct Point{
  ldouble x,y;
  Point operator + (const Point p)const{
    return (Point){x+p.x,y+p.y};
  }
  Point operator - (const Point p)const{
    return (Point){x-p.x,y-p.y};
  }
  Point operator * (const ldouble r)const{
    return (Point){x*r,y*r};
  }
};
bool eq(Point a,Point b){return ( eq(a.x,b.x) && eq(a.y,b.y) );}
  
typedef Point Vector;
 
ldouble dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
ldouble cross(Vector a,Vector b){return a.x*b.y-b.x*a.y;}
ldouble norm(Vector v){return dot(v,v);}
ldouble abs(Vector v){return sqrt(norm(v));}
  
  
Point project(Point a,Point b,Point p){
  Point base=b-a;
  ldouble r=dot(p-a,base)/norm(base);
  return a+base*r;
}
 
int n;
ldouble A,B;
vector<Point> t;
Point s,g;
ldouble ans;
  
ldouble func0(double H,double W){
  ldouble a=1.0;
  ldouble b=-2.0*W;
  ldouble c=W*W-(A*A*H*H)/(B*B-A*A);
  if(b*b-4.0*a*c<0)return min(H*B+W*A, sqrt(H*H+W*W)*B);
  ldouble t = (-b+sqrt(b*b-4.0*a*c))/(2.0*a);
  if(t>W){
    t=(-b-sqrt(b*b-4.0*a*c))/(2.0*a);
    if(t<0)return 0;
  }
  return t;
}
ldouble func02(Point a,Point b,Point g){
  Point D=project(a,b,g);
  return func0( abs(g-D) , abs(a-D) );
}
ldouble func(ldouble H,ldouble W){
  ldouble t=func0(H,W);
  ldouble ff = t*A+B*sqrt((W-t)*(W-t)+H*H );
  return ff;
} 
ldouble func2(Point a,Point b,Point g){
  Point D=project(a,b,g);
  return func( abs(g-D) , abs(a-D) );
}
  
void solve(){
  vector<Point> T;
  for(int i=0;i<n;i++){
    T.push_back(t[i]);
    if(i+1<n){
      ldouble tt = func02(t[i],t[i+1],g);
      Vector base=t[i+1]-t[i];      
      Point next =  t[i]+ base*( tt /abs(base) );
      if(!eq(next,t[i])&&!eq(next,t[i+1])
         && eq(abs(t[i]-next)+abs(t[i+1]-next),abs(t[i]-t[i+1]))
         )T.push_back(next);
    }
  }
    
  t=T;
  n=t.size();
  vector<ldouble> u(n);  
  u[0]=0;
  u[1]=abs(t[0]-t[1])*A;
  for(int i=2;i<n;i++){
    u[i]=u[i-1]+abs(t[i]-t[i-1])*A;
    for(int j=1;j<i;j++){
      u[i]=min(u[i],u[j-1]+func2(t[j-1],t[j],t[i]));
      u[i]=min(u[i],u[j-1]+func2(t[i],t[i-1],t[j-1]));
    }
  }
  for(int i=0;i+1<n;i++){
    ldouble na = u[i]+func2(t[i],t[i+1],g);
    ans=min(ans,na);
  }
}
  
int main(){
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  while(1){
    vector<Point> nt;
    cin>>n;
    if(n==0)break;
    t.clear();t.resize(n);
    for(int i=0;i<n;i++)cin>>t[i].x>>t[i].y;
    cin>>A>>B>>s.x>>s.y>>g.x>>g.y;
    int flg=0,f=-1;
    for(int i=0;i<n;i++){
      int j=(i+1)%n;      
      if(eq(s,t[i]))flg=1;
      if(eq( abs(s-t[i])+abs(s-t[j]) , abs(t[i]-t[j]) )){
        f=j;
        break;
      }
    }
    if(flg==0)nt.push_back(s);
    else f=(f+n-1)%n;
    for(int j=0;j<n;j++)nt.push_back(t[(f+j)%n]);
    n=nt.size();
    t=nt;
    ans=abs(s-g)*B;
    solve();
    reverse(t.begin()+1,t.end());
    solve();
    double ans2=ans;
    printf("%.14f\n",ans2);
  }
  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3156
final_rank: 4

code_snippet: #include<bits/stdc++.h>
#define MAX 100
#define inf 1<<29
#define linf 1e16
#define eps (1e-8)
#define mod 1000000007
#define pi acos(-1)
#define phi (1.0+sqrt(5))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):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 k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ 
    return (!equals(x,p.x) ? x-p.x<-eps : y-p.y<-eps);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

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

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

int n;
double tg,tw;
Polygon p;
vector<Point> vp;
vector<pid> g[MAX];
Point s,t;
int S,T;

void init(){
  p.clear();
  vp.clear();
  FOR(i,0,MAX)g[i].clear();
}

Point getPoint(Point a,Point b,Point c){
  Vector v=b-a;
  v=v/abs(v);
  double L=0.0,R=abs(b-a);
  FOR(i,0,40){
    double m1=(L*phi+R)/(1.0+phi);
    double m2=(L+R*phi)/(1.0+phi);
    double res1=(abs(v*m1))*tg+abs(a+v*m1-c)*tw;
    double res2=(abs(v*m2))*tg+abs(a+v*m2-c)*tw;
    if(res1<res2)R=m2;
    else L=m1;
  }
  return a+v*L;
}

double dijkstra(){
  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[S]=0;
  pq.push(mp(0,S));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();
    if(d[u.s]-u.f<-eps)continue;
    if(u.s==T)return d[u.s];

    FOR(i,0,g[u.s].size()){
      int next=g[u.s][i].f;
      double cost=d[u.s]+g[u.s][i].s;
      if(cost-d[next]<-eps){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return inf;
}

double solve(){
  FOR(i,0,n){
    vp.pb(getPoint(p[i],p[(i+1)%n],s));
    vp.pb(getPoint(p[i],p[(i+1)%n],t));
    vp.pb(getPoint(p[(i+1)%n],p[i],s));
    vp.pb(getPoint(p[(i+1)%n],p[i],t));
  }
  vp.pb(s);
  FOR(i,0,n){
    Segment s(p[i],p[(i+1)%n]);
    vector<pdi> list;
    FOR(j,0,vp.size()){
      if(ccw(s.p1,s.p2,vp[j])==0)list.pb(mp(abs(s.p1-vp[j]),j));
    }
    sort(all(list));
    FOR(j,0,list.size()-1){
      int a=list[j].s,b=list[j+1].s;
      g[a].pb(mp(b,abs(vp[a]-vp[b])*tg));
      g[b].pb(mp(a,abs(vp[a]-vp[b])*tg));
    }
  }
  vp.pb(t);
  FOR(i,0,vp.size()){
    if(vp[i]==s)S=i;
    if(vp[i]==t)T=i;
  }
  FOR(i,0,vp.size())if(i!=T)g[i].pb(mp(T,abs(vp[i]-t)*tw));
  FOR(i,0,vp.size())if(i!=S)g[S].pb(mp(i,abs(vp[i]-s)*tw));

  return dijkstra();
}

int main()
{
  while(cin>>n && n){
    init();
    FOR(i,0,n){
      int x,y;
      cin>>x>>y;
      p.pb(Point(x,y));
      vp.pb(Point(x,y));
    }
    cin>>tg>>tw;
    cin>>s.x>>s.y>>t.x>>t.y;
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3144
final_rank: 5

code_snippet: #include<bits/stdc++.h>
#define MAX 100
#define inf 1<<29
#define linf 1e16
#define eps (1e-10)
#define mod 1000000007
#define pi acos(-1)
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):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 k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ 
    return (!equals(x,p.x) ? x-p.x<-eps : y-p.y<-eps);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

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

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

int n;
double tg,tw;
Polygon p;
vector<Point> vp;
vector<pid> g[MAX];
Point s,t;
int S,T;

void init(){
  p.clear();
  vp.clear();
  FOR(i,0,MAX)g[i].clear();
}

Point getPoint(Point a,Point b,Point c){
  Vector v=b-a;
  v=v/abs(v);
  double L=0.0,R=abs(b-a);
  FOR(i,0,50){
    double m1=(L+L+R)/3.0;
    double m2=(L+R+R)/3.0;
    double res1=(abs(v*m1))*tg+abs(a+v*m1-c)*tw;
    double res2=(abs(v*m2))*tg+abs(a+v*m2-c)*tw;
    if(res1-res2<-eps)R=m2;
    else L=m1;
  }
  return a+v*L;
}

double dijkstra(){
  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[S]=0;
  pq.push(mp(0,S));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();
    if(d[u.s]-u.f<-eps)continue;
    if(u.s==T)return d[u.s];

    FOR(i,0,g[u.s].size()){
      int next=g[u.s][i].f;
      double cost=d[u.s]+g[u.s][i].s;
      if(cost-d[next]<-eps){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return inf;
}

double solve(){
  FOR(i,0,n){
    vp.pb(getPoint(p[i],p[(i+1)%n],s));
    vp.pb(getPoint(p[i],p[(i+1)%n],t));
    vp.pb(getPoint(p[(i+1)%n],p[i],s));
    vp.pb(getPoint(p[(i+1)%n],p[i],t));
  }
  vp.pb(s);
  FOR(i,0,n){
    Segment s(p[i],p[(i+1)%n]);
    vector<pdi> list;
    FOR(j,0,vp.size()){
      if(ccw(s.p1,s.p2,vp[j])==0)list.pb(mp(abs(s.p1-vp[j]),j));
    }
    sort(all(list));
    FOR(j,0,list.size()-1){
      int a=list[j].s,b=list[j+1].s;
      g[a].pb(mp(b,abs(vp[a]-vp[b])*tg));
      g[b].pb(mp(a,abs(vp[a]-vp[b])*tg));
    }
  }
  vp.pb(t);
  FOR(i,0,vp.size()){
    if(vp[i]==s)S=i;
    if(vp[i]==t)T=i;
  }
  FOR(i,0,vp.size())if(i!=T)g[i].pb(mp(T,abs(vp[i]-t)*tw));
  FOR(i,0,vp.size())if(i!=S)g[S].pb(mp(i,abs(vp[i]-s)*tw));

  return dijkstra();
}

int main()
{
  while(cin>>n && n){
    init();
    FOR(i,0,n){
      int x,y;
      cin>>x>>y;
      p.pb(Point(x,y));
      vp.pb(Point(x,y));
    }
    cin>>tg>>tw;
    cin>>s.x>>s.y>>t.x>>t.y;
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3192
final_rank: 6

code_snippet: #include<bits/stdc++.h>
#define MAX 100
#define inf 1<<29
#define linf 1e16
#define eps (1e-8)
#define mod 1000000007
#define pi acos(-1)
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):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 k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ 
    return (!equals(x,p.x) ? x-p.x<-eps : y-p.y<-eps);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

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

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

vector<Point> unique(vector<Point> vp){
  vector<Point> res;
  if(vp.empty())return res;
  sort(all(vp));
  res.pb(vp[0]);
  FOR(i,1,vp.size())if(!(res.back()==vp[i]))res.pb(vp[i]);
  return res;
}

int n;
double tg,tw;
Polygon p;
vector<Point> vp;
vector<pid> g[MAX];
Point s,t;
int S,T;

void init(){
  p.clear();
  vp.clear();
  FOR(i,0,MAX)g[i].clear();
}

Point getPoint(Point a,Point b,Point c){
  Vector v=b-a;
  v=v/abs(v);
  double L=0.0,R=abs(b-a);
  FOR(i,0,50){
    double m1=(L+L+R)/3.0;
    double m2=(L+R+R)/3.0;
    double res1=(abs(v*m1))*tg+abs(a+v*m1-c)*tw;
    double res2=(abs(v*m2))*tg+abs(a+v*m2-c)*tw;
    if(res1<res2)R=m2;
    else L=m1;
  }
  return a+v*L;
}

double dijkstra(){
  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[S]=0;
  pq.push(mp(0,S));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();
    if(d[u.s]-u.f<-eps)continue;
    if(u.s==T)return d[u.s];

    FOR(i,0,g[u.s].size()){
      int next=g[u.s][i].f;
      double cost=d[u.s]+g[u.s][i].s;
      if(cost-d[next]<-eps){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return inf;
}

double solve(){
  FOR(i,0,n){
    vp.pb(getPoint(p[i],p[(i+1)%n],s));
    vp.pb(getPoint(p[i],p[(i+1)%n],t));
    vp.pb(getPoint(p[(i+1)%n],p[i],s));
    vp.pb(getPoint(p[(i+1)%n],p[i],t));
  }
  vp.pb(s);
 // vp=unique(vp);
  FOR(i,0,n){
    Segment s(p[i],p[(i+1)%n]);
    vector<pdi> list;
    FOR(j,0,vp.size()){
      if(ccw(s.p1,s.p2,vp[j])==0)list.pb(mp(abs(s.p1-vp[j]),j));
    }
    sort(all(list));
    FOR(j,0,list.size()-1){
      int a=list[j].s,b=list[j+1].s;
      g[a].pb(mp(b,abs(vp[a]-vp[b])*tg));
      g[b].pb(mp(a,abs(vp[a]-vp[b])*tg));
    }
  }
  vp.pb(t);
  FOR(i,0,vp.size()){
    if(vp[i]==s)S=i;
    if(vp[i]==t)T=i;
  }
  FOR(i,0,vp.size())if(i!=T)g[i].pb(mp(T,abs(vp[i]-t)*tw));
  FOR(i,0,vp.size())if(i!=S)g[S].pb(mp(i,abs(vp[i]-s)*tw));

  return dijkstra();
}

int main()
{
  while(cin>>n && n){
    init();
    FOR(i,0,n){
      int x,y;
      cin>>x>>y;
      p.pb(Point(x,y));
      vp.pb(Point(x,y));
    }
    cin>>tg>>tw;
    cin>>s.x>>s.y>>t.x>>t.y;
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3300
final_rank: 10

code_snippet: #include<bits/stdc++.h>
#define MAX 100
#define inf 1<<29
#define linf 1e16
#define eps (1e-8)
#define mod 1000000007
#define pi acos(-1)
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

  
class Point{
public:
  double x,y;
  Point(double x=0,double y=0):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 k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return (x!=p.x ? x<p.x : y<p.y);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

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

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

vector<Point> unique(vector<Point> vp){
  vector<Point> res;
  if(vp.empty())return res;
  res.pb(vp[0]);
  FOR(i,0,vp.size())if(!(res.back()==vp[i]))res.pb(vp[i]);
  return res;
}

int n;
double tg,tw;
Polygon p;
vector<Point> vp;
vector<pid> g[MAX];
Point s,t;
int S,T;

void init(){
  p.clear();
  vp.clear();
  FOR(i,0,MAX)g[i].clear();
}

Point getPoint(Point a,Point b,Point c){
  Vector v=b-a;
  v=v/abs(v);
  double L=0.0,R=abs(b-a);
  FOR(i,0,50){
    double m1=(L+L+R)/3.0;
    double m2=(L+R+R)/3.0;
    double res1=(abs(v*m1))*tg+abs(a+v*m1-c)*tw;
    double res2=(abs(v*m2))*tg+abs(a+v*m2-c)*tw;
    if(res1<res2)R=m2;
    else L=m1;
  }
  return a+v*L;
}

double dijkstra(){
  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[S]=0;
  pq.push(mp(0,S));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();
    if(d[u.s]-u.f<-eps)continue;
    if(u.s==T)return d[u.s];

    FOR(i,0,g[u.s].size()){
      int next=g[u.s][i].f;
      double cost=d[u.s]+g[u.s][i].s;
      if(cost-d[next]<-eps){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return inf;
}

double solve(){
  FOR(i,0,n){
    vp.pb(getPoint(p[i],p[(i+1)%n],s));
    vp.pb(getPoint(p[i],p[(i+1)%n],t));
    vp.pb(getPoint(p[(i+1)%n],p[i],s));
    vp.pb(getPoint(p[(i+1)%n],p[i],t));
  }
  vp.pb(s);
  vp=unique(vp);
  FOR(i,0,n){
    Segment s(p[i],p[(i+1)%n]);
    vector<pdi> list;
    FOR(j,0,vp.size()){
      if(ccw(s.p1,s.p2,vp[j])==0)list.pb(mp(abs(s.p1-vp[j]),j));
    }
    sort(all(list));
    FOR(j,0,list.size()-1){
      int a=list[j].s,b=list[j+1].s;
      g[a].pb(mp(b,abs(vp[a]-vp[b])*tg));
      g[b].pb(mp(a,abs(vp[a]-vp[b])*tg));
    }
  }
  vp.pb(t);
  FOR(i,0,vp.size()){
    if(vp[i]==s)S=i;
    if(vp[i]==t)T=i;
  }
  FOR(i,0,vp.size())if(i!=T)g[i].pb(mp(T,abs(vp[i]-t)*tw));
  FOR(i,0,vp.size())if(i!=S)g[S].pb(mp(i,abs(vp[i]-s)*tw));

  return dijkstra();
}

int main()
{
  while(cin>>n && n){
    init();
    FOR(i,0,n){
      int x,y;
      cin>>x>>y;
      p.pb(Point(x,y));
      vp.pb(Point(x,y));
    }
    cin>>tg>>tw;
    cin>>s.x>>s.y>>t.x>>t.y;
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3228
final_rank: 7

code_snippet: #include<bits/stdc++.h>
#define MAX 100
#define inf 1<<29
#define linf 1e16
#define eps (1e-8)
#define mod 1000000007
#define pi acos(-1)
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

  
class Point{
public:
  double x,y;
  Point(double x=0,double y=0):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 k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return (x!=p.x ? x<p.x : y<p.y);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

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

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

vector<Point> unique(vector<Point> vp){
  vector<Point> res;
  if(vp.empty())return res;
  res.pb(vp[0]);
  FOR(i,0,vp.size())if(!(res.back()==vp[i]))res.pb(vp[i]);
  return res;
}

int n;
double tg,tw;
Polygon p;
vector<Point> vp;
vector<pid> g[MAX];
Point s,t;
int S,T;

void init(){
  p.clear();
  vp.clear();
  FOR(i,0,MAX)g[i].clear();
}

Point getPoint(Point a,Point b,Point c){
  Vector v=b-a;
  v=v/abs(v);
  double L=0.0,R=abs(b-a);
  FOR(i,0,100){
    double m1=(L+L+R)/3.0;
    double m2=(L+R+R)/3.0;
    double res1=(abs(v*m1))*tg+abs(a+v*m1-c)*tw;
    double res2=(abs(v*m2))*tg+abs(a+v*m2-c)*tw;
    if(res1<res2)R=m2;
    else L=m1;
  }
  return a+v*L;
}

double dijkstra(){
  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[S]=0;
  pq.push(mp(0,S));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();
    if(d[u.s]-u.f<-eps)continue;
    if(u.s==T)return d[u.s];

    FOR(i,0,g[u.s].size()){
      int next=g[u.s][i].f;
      double cost=d[u.s]+g[u.s][i].s;
      if(cost-d[next]<-eps){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return inf;
}

double solve(){
  FOR(i,0,n){
    vp.pb(getPoint(p[i],p[(i+1)%n],s));
    vp.pb(getPoint(p[i],p[(i+1)%n],t));
    vp.pb(getPoint(p[(i+1)%n],p[i],s));
    vp.pb(getPoint(p[(i+1)%n],p[i],t));
  }
  vp.pb(s);
  vp=unique(vp);
  FOR(i,0,n){
    Segment s(p[i],p[(i+1)%n]);
    vector<pdi> list;
    FOR(j,0,vp.size()){
      if(ccw(s.p1,s.p2,vp[j])==0)list.pb(mp(abs(s.p1-vp[j]),j));
    }
    sort(all(list));
    FOR(j,0,list.size()-1){
      int a=list[j].s,b=list[j+1].s;
      g[a].pb(mp(b,abs(vp[a]-vp[b])*tg));
      g[b].pb(mp(a,abs(vp[a]-vp[b])*tg));
    }
  }
  vp.pb(t);
  FOR(i,0,vp.size()){
    if(vp[i]==s)S=i;
    if(vp[i]==t)T=i;
  }
  FOR(i,0,vp.size())if(i!=T)g[i].pb(mp(T,abs(vp[i]-t)*tw));
  FOR(i,0,vp.size())if(i!=S)g[S].pb(mp(i,abs(vp[i]-s)*tw));

  return dijkstra();
}

int main()
{
  while(cin>>n && n){
    init();
    FOR(i,0,n){
      int x,y;
      cin>>x>>y;
      p.pb(Point(x,y));
      vp.pb(Point(x,y));
    }
    cin>>tg>>tw;
    cin>>s.x>>s.y>>t.x>>t.y;
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3148
final_rank: 8

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

using namespace std;

inline long double add(long double a, long double b){
    return abs(a+b)<(1e-11)*(abs(a)+abs(b)) ? 0.0 : a+b;
}

struct vec{
    long double x,y;
    vec operator-(vec b){
        return (vec){add(x,-b.x),add(y,-b.y)};
    }
    vec operator+(vec b){
        return (vec){add(x,b.x),add(y,b.y)};
    }
    vec operator*(long double d){
        return (vec){x*d,y*d};
    }
    bool operator==(vec b){
        return x==b.x&&y==b.y;
    }
    bool operator!=(vec b){
        return x!=b.x||y!=b.y;
    }
    long double dot(vec v){
        return add(x*v.x,y*v.y);
    }
    long double cross(vec v){
        return add(x*v.y,-y*v.x);
    }
    long double norm(){
        return sqrt(x*x+y*y);
    }
};

int ccw(vec& a, vec& b, vec& c){
    vec ab = b-a, ac = c-a;
    long double o = ab.cross(ac);
    if(o>0) return 1; //CCW
    if(o<0) return -1; //CW
    if(ab.dot(ac)<0){
        return 2; //C-A-B
    }else{
        if(ab.dot(ab)<ac.dot(ac)){
            return -2; //A-B-C
        }else{
            return 0; //A-C-B
        }
    }
}

void print_path(vector<pair<int,vec>>&P);
long double t_sum(vector<pair<int,vec>>&P, long double tg, long double tw);

vec ternarysearch(vec& p0, vec& p1, vec& p2, long double tg, long double tw){
    //???p0??????p2??????????????????p2p3?????????????????£?????????????????§????????????????????????????????????
    long double left=1.0/3.0,right=2.0/3.0;
    long double t,t1,t2;
    vec P1,P2;
    while(true){
        P1=p1*(1-left)+p2*left;
        P2=p1*(1-right)+p2*right;
        t1=(p0-P1).norm()*tw+(p2-P1).norm()*tg;
        t2=(p0-P2).norm()*tw+(p2-P2).norm()*tg;
        if(abs(t1-t2)<1e-11){
            t=(left+right)/2;
            if(1.0-t<1e-8){
                return p2;
            }else if(t<1e-8){
                return p1;
            }else{
                return P1;
            }
        }
        if(t1<t2){
            right=(2*left+right)/3;
            left=2*left-right;
        }else{
            left=(2*right+left)/3;
            right=2*right-left;
        }
    }
}

struct Segment{
    int begin,end;
    vector<int> P;
    Segment(int a, int b){
        begin=a, end=b;
        P.push_back(a);
        P.push_back(b);
    }
};

struct Edge{
    int to;
    long double t;
    Edge(int a, long double b){
        to=a, t=b;
    }
};

struct Point{
    vec v;
    vector<Edge> E;
    Point(vec v){
        this->v=v;
    }
};

long double solve(vector<vec>& v, vec& S, vec& T, long double tg, long double tw){
    int n = v.size();
    vector<Point> V;
    for(int i=0;i<n;i++){
        if((v[i]-S).norm()<1e-8){//S?????????????????????
            V.push_back(Point(S));
            for(int j=i+1;j!=i;j=(j+1)%n){
                V.push_back(Point(v[j]));
            }
            break;
        }else if(!ccw(v[i],v[(i+1)%n],S)){//S??????????????????
            V.push_back(Point(S));
            i=(i+1)%n;
            for(int j=0;j<n;j++){
                V.push_back(Point(v[(i+j)%n]));
            }
            break;
        }
    }
    n=V.size();
    vector<Segment> L;
    for(int i=0;i<V.size();i++){
        L.push_back(Segment(i,(i+1)%n));
    }
    V.push_back(T);
    n=V.size();
    int iT=V.size()-1;
    for(int i=0;i<n;i++){
        for(auto& s:L){
            if(s.begin==i||s.end==i) continue;
            vec M;
            M=ternarysearch(V[i].v,V[s.begin].v,V[s.end].v,tg,tw);
            if(M!=V[s.begin].v&&M!=V[s.end].v){
                V.push_back(M);
                V.back().E.push_back(Edge(i,(V[i].v-M).norm()*tw));
                V[i].E.push_back(Edge(V.size()-1,(V[i].v-M).norm()*tw));
                s.P.push_back(V.size()-1);
            }
            M=ternarysearch(V[i].v,V[s.end].v,V[s.begin].v,tg,tw);
            if(M!=V[s.begin].v&&M!=V[s.end].v){
                V.push_back(M);
                V.back().E.push_back(Edge(i,(V[i].v-M).norm()*tw));
                V[i].E.push_back(Edge(V.size()-1,(V[i].v-M).norm()*tw));
                s.P.push_back(V.size()-1);
            }
        }
    }
    //????§???¢?????????+S+T????£?????????¶
    for(int i=0;i<=iT;i++){
        for(int j=i+2;j<=iT;j++){
            V[i].E.push_back(Edge(j,(V[i].v-V[j].v).norm()*tw));
            V[j].E.push_back(Edge(i,(V[i].v-V[j].v).norm()*tw));
        }
    }

    //????§???¢????????????????????????????????¶???
    for(auto& s:L){
        for(auto& p1:s.P){
            for(auto& p2:s.P){
                if(p1!=p2){
                    V[p1].E.push_back(Edge(p2,(V[p1].v-V[p2].v).norm()*tg));
                    V[p2].E.push_back(Edge(p1,(V[p1].v-V[p2].v).norm()*tg));
                }
            }
        }
    }
    //?§???????0????????????iT?????????????????????
    typedef pair<long double, int> Q;
    priority_queue<Q, vector<Q>, greater<Q>> que;
    long double minimum_time[V.size()];
    fill(minimum_time,minimum_time+V.size(),1e10);
    int s=0;
    minimum_time[s]=0;
    que.push(Q(0,s));
    while(!que.empty()){
        Q q=que.top();
        que.pop();
        int i = q.second;
        if(i==iT) return minimum_time[i];
        if(minimum_time[i]<q.first) continue;
        for(auto& e:V[i].E){
            if(minimum_time[e.to]>minimum_time[i]+e.t){
                minimum_time[e.to]=minimum_time[i]+e.t;
                que.push(Q(minimum_time[e.to],e.to));
            }
        }
    }
    return 0;
}

int main(){
    int n;
    long double tg,tw;
    vec S,T;
    vector<vec> V;

    while(cin >> n, n!=0){
        V.clear();
        for(int i=0;i<n;i++){
            long double x,y;
            cin >> x >> y;
            V.push_back((vec){.x=x,.y=y});
        }
        cin >> tg >> tw;
        cin >> S.x >> S.y;
        cin >> T.x >> T.y;

        cout.precision(8);
        cout << fixed;
        cout << solve(V,S,T,tg,tw) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 3204
final_rank: 13

code_snippet: #include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <complex>
 
using namespace std;
 
typedef long long ll;
typedef complex<double> P;
 
#define REP(i,n) for(ll i=0;i<(n);++i)
#define DEBUG(x) cout<<#x<<": "<<(x)<<endl
 
#define N_MAX 10
int n;
P ps[N_MAX+1];
int tg,tw;
P start,goal;
double pslen[N_MAX+1];
double pslensum[N_MAX*2+1];

int pai,pbi,sti;
P pa,pb;

double minestval = 1e18;
int minestpai = -1,minestpbi = -1;
bool hack = false;
 
double calc(){
    double result = 0.0;
    if(pai != sti){
        result += abs(pa-start)*tw;
    }
    if(pai == sti){
        if(sti != pbi){
            double tmp = 0.0;
            if(sti<pbi)
                tmp += (pslensum[pbi-1] - pslensum[sti])*tg;
            else
                tmp += (pslensum[pbi+n-1] - pslensum[sti])*tg;
            tmp += abs(ps[sti+1]-start)*tg;
            tmp += abs(pb-ps[pbi])*tg;

            double tmp2 = 0.0;
            if(sti>pbi)
                tmp2 += (pslensum[sti-1] - pslensum[pbi])*tg;
            else
                tmp2 += (pslensum[sti+n-1] - pslensum[pbi])*tg;
            tmp2 += abs(start-ps[sti])*tg;
            tmp2 += abs(ps[pbi+1]-pb)*tg;

            result += min(tmp,tmp2);
        }else{
            result += abs(pb-start)*tg;
        }
    }else{
        if(pai != pbi){
            double tmp = 0.0;
            if(pai<pbi)
                tmp += (pslensum[pbi-1] - pslensum[pai])*tg;
            else
                tmp += (pslensum[pbi+n-1] - pslensum[pai])*tg;
            tmp += abs(ps[pai+1]-pa)*tg;
            tmp += abs(pb-ps[pbi])*tg;

            double tmp2 = 0.0;
            if(pai>pbi)
                tmp2 += (pslensum[pai-1] - pslensum[pbi])*tg;
            else
                tmp2 += (pslensum[pai+n-1] - pslensum[pbi])*tg;
            tmp2 += abs(pa-ps[pai])*tg;
            tmp2 += abs(ps[pbi+1]-pb)*tg;

            result += min(tmp,tmp2);
        }else{
            result += abs(pb-pa)*tg;
        }
    }
    result += abs(goal-pb)*tw;
    if(!hack && result < minestval){
        minestval = result;
        minestpai = pai;
        minestpbi = pbi;
    }
    return result;
}

int T = 10;

double solve2(){
    double result = 1e18;
    REP(i,n){
        if(hack && i!=minestpbi) continue;
        pbi = i;
        double left = 0.0;
        double right = 1.0;
        REP(_,T){
            double midl = (left*2.0+right)/3.0;
            pb = ps[i] + (ps[i+1]-ps[i])*midl;
            double resl = calc();
            double midr = (left+right*2.0)/3.0;
            pb = ps[i] + (ps[i+1]-ps[i])*midr;
            double resr = calc();
            if(resl<resr)right = midr;
            else left = midl;
        }
        pb = ps[i]+(ps[i+1]-ps[i])*left;
        result = min(result,calc());
    }
    return result;
}
 
double solve(){
    // determine PointA
    double result = 1e18;
    REP(i,n){
        if(hack && i!=minestpai) continue;
        // edge from ps[i] to ps[i+1]
        pai = i;
        double left = 0.0;
        double right = 1.0;
        REP(_,T){
            double midl = (left*2.0+right)/3.0;
            pa = ps[i] + (ps[i+1]-ps[i])*midl;
            double resl = solve2();
            double midr = (left+right*2.0)/3.0;
            pa = ps[i] + (ps[i+1]-ps[i])*midr;
            double resr = solve2();
            if(resl<resr)right = midr;
            else left = midl;
        }
        pa = ps[i]+(ps[i+1]-ps[i])*left;
        result = min(result,solve2());
    }
    return result;
}
 
int main(){
    cout.precision(20);
    while(true){
        // input
        cin>>n;
        if(!n)break;
        int x,y;
        REP(i,n){
            cin>>x>>y;
            ps[i] = P(x,y);
        }
        ps[n] = ps[0];
        cin>>tg>>tw;
        cin>>x>>y;
        start = P(x,y);
        cin>>x>>y;
        goal = P(x,y);
 
        REP(i,n) pslen[i] = abs(ps[i+1]-ps[i]);
        REP(i,2*n+1){
            pslensum[i] = pslen[i%n];
            if(i!=0) pslensum[i] += pslensum[i-1];
        }
        REP(i,n){
            if( abs((conj(ps[i+1]-ps[i])*(start-ps[i])).imag()) < 1e-9 ){
                sti = i;
                break;
            }
        }
        minestval = 1e18;
        T = 20;
        hack = false;
        solve();
        T = 100;
        hack = true;
        double result = solve();
        cout<<fixed<<result<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 6330
memory_kb: 1260
final_rank: 20

code_snippet: #include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
using namespace std;
const double EPS = 1e-10;
const double INF = 1e+10;
const double PI = acos(-1);
int sig(double r) { return (r < -EPS) ? -1 : (r > +EPS) ? +1 : 0; }
inline double ABS(double a){return max(a,-a);}
struct Pt {
	double x, y;
	Pt() {}
	Pt(double x, double y) : x(x), y(y) {}
	Pt operator+(const Pt &a) const { return Pt(x + a.x, y + a.y); }
	Pt operator-(const Pt &a) const { return Pt(x - a.x, y - a.y); }
	Pt operator*(const Pt &a) const { return Pt(x * a.x - y * a.y, x * a.y + y * a.x); }
	Pt operator-() const { return Pt(-x, -y); }
	Pt operator*(const double &k) const { return Pt(x * k, y * k); }
	Pt operator/(const double &k) const { return Pt(x / k, y / k); }
	double ABS() const { return sqrt(x * x + y * y); }
	double abs2() const { return x * x + y * y; }
	double arg() const { return atan2(y, x); }
	double dot(const Pt &a) const { return x * a.x + y * a.y; }
	double det(const Pt &a) const { return x * a.y - y * a.x; }
};
double tri(const Pt &a, const Pt &b, const Pt &c) { return (b - a).det(c - a); }
int iSP(Pt a, Pt b, Pt c) {
	int s = sig((b - a).det(c - a));
	if (s) return s;
	if (sig((b - a).dot(c - a)) < 0) return -2; // c-a-b
	if (sig((a - b).dot(c - b)) < 0) return +2; // a-b-c
	return 0;
}
Pt pLL(Pt a, Pt b, Pt c, Pt d) {
	b = b - a; d = d - c; return a + b * (c - a).det(d) / b.det(d);
}
Pt hLP(Pt a,Pt b,Pt c){
	return pLL(a,b,c,c+(b-a)*Pt(0,1));
}
//inside: +1 on: 0 outside: -1
int sGP(int n, Pt p[], Pt a) {
	int side = -1, i;
	p[n] = p[0];
	for (i = 0; i < n; ++i) {
		Pt p0 = p[i] - a, p1 = p[i + 1] - a;
		if (sig(p0.det(p1)) == 0 && sig(p0.dot(p1)) <= 0) return 0;
		if (p0.y > p1.y) swap(p0, p1);
		if (sig(p0.y) <= 0 && 0 < sig(p1.y) && sig(p0.det(p1)) > 0) side = -side;
	}
	return side;
}

Pt p[20];
Pt h[20];
double ijk[1100];
int v[1100];
int main(){
	int a;
	while(scanf("%d",&a),a){
		double tg,tw;
		for(int i=0;i<a;i++){
			double X,Y;
			scanf("%lf%lf",&X,&Y);
			p[i]=Pt(X,Y);
		}
		p[a]=p[0];
		scanf("%lf%lf",&tg,&tw);
		Pt s,t;
		double X,Y;
		scanf("%lf%lf",&X,&Y);
		s=Pt(X,Y);
		scanf("%lf%lf",&X,&Y);
		t=Pt(X,Y);
		double th=asin(tg/tw);
		for(int i=0;i<a;i++){
			h[i]=hLP(p[i],p[i+1],t);
		}
		vector<Pt> hb;
		hb.push_back(s);
		hb.push_back(t);
		for(int i=0;i<a;i++){
			hb.push_back(p[i]);
		}
		for(int i=0;i<a;i++){
			for(int j=0;j<a;j++){
				if(i==j||i==j+1)continue;
				Pt tmp=hLP(p[j],p[j+1],p[i]);
				double dist=(tmp-p[i]).ABS();
				double len=dist*tan(th);
				Pt vec=p[j+1]-p[j];
				vec=vec/(vec.ABS())*len;
				Pt t1=tmp+vec;
				Pt t2=tmp-vec;
				if(iSP(p[j],t1,p[j+1])==2)hb.push_back(t1);
				if(iSP(p[j],t2,p[j+1])==2)hb.push_back(t2);
			}
		}
		for(int j=0;j<a;j++){
			Pt tmp=hLP(p[j],p[j+1],t);
			double dist=(tmp-t).ABS();
			double len=dist*tan(th);
			Pt vec=p[j+1]-p[j];
			vec=vec/(vec.ABS())*len;
			Pt t1=tmp+vec;
			Pt t2=tmp-vec;
			if(iSP(p[j],t1,p[j+1])==2)hb.push_back(t1);
			if(iSP(p[j],t2,p[j+1])==2)hb.push_back(t2);
		}
		for(int j=0;j<a;j++){
			Pt tmp=hLP(p[j],p[j+1],s);
			double dist=(tmp-s).ABS();
			double len=dist*tan(th);
			Pt vec=p[j+1]-p[j];
			vec=vec/(vec.ABS())*len;
			Pt t1=tmp+vec;
			Pt t2=tmp-vec;
			if(iSP(p[j],t1,p[j+1])==2)hb.push_back(t1);
			if(iSP(p[j],t2,p[j+1])==2)hb.push_back(t2);
		}
		int sz=hb.size();
		for(int i=0;i<sz;i++){
			v[i]=0;
			ijk[i]=999999999;
		}
		ijk[0]=0;
		for(int i=0;i<sz;i++){
			int at=0;
			double tmp=999999999;
			for(int j=0;j<sz;j++){
				if(!v[j]&&tmp>ijk[j]){
					at=j;tmp=ijk[j];
				}
			}
			v[at]=1;
			for(int j=0;j<sz;j++){
				if(v[j])continue;
				Pt M=(hb[at]+hb[j])/2;
				double toc=ijk[at];
				if(sGP(a,p,M)==0)toc+=(hb[at]-hb[j]).ABS()*tg;
				else toc+=(hb[at]-hb[j]).ABS()*tw;
				ijk[j]=min(ijk[j],toc);
			}
		}
		//for(int i=0;i<sz;i++)printf("(%f %f): %f\n",hb[i].x,hb[i].y,ijk[i]);
		printf("%.12f\n",ijk[1]);
	}
}
accuracy: 1
time_ms: 30
memory_kb: 1192
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
 
typedef long double ldouble;
const ldouble eps = 0.000000001;
bool eq(ldouble a,ldouble b){return (-eps<a-b && a-b<eps);}

struct Point{
  ldouble x,y;
  Point operator + (const Point p)const{
    return (Point){x+p.x,y+p.y};
  }
  Point operator - (const Point p)const{
    return (Point){x-p.x,y-p.y};
  }
  Point operator * (const ldouble r)const{
    return (Point){x*r,y*r};
  }
};
bool eq(Point a,Point b){return ( eq(a.x,b.x) && eq(a.y,b.y) );}
 
typedef Point Vector;

ldouble dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
ldouble cross(Vector a,Vector b){return a.x*b.y-b.x*a.y;}
ldouble norm(Vector v){return dot(v,v);}
ldouble abs(Vector v){return sqrt(norm(v));}
 
 
Point project(Point a,Point b,Point p){
  Point base=b-a;
  ldouble r=dot(p-a,base)/norm(base);
  return a+base*r;
}

int n;
ldouble A,B;
vector<Point> t;
Point s,g;
ldouble ans;
 
ldouble func0(double H,double W){
  ldouble a=1.0;
  ldouble b=-2.0*W;
  ldouble c=W*W-(A*A*H*H)/(B*B-A*A);
  if(b*b-4.0*a*c<0)return min(H*B+W*A, sqrt(H*H+W*W)*B);
  ldouble t = (-b+sqrt(b*b-4.0*a*c))/(2.0*a);
  if(t>W){
    t=(-b-sqrt(b*b-4.0*a*c))/(2.0*a);
    if(t<0)return 0;
  }
  return t;
}
ldouble func02(Point a,Point b,Point g){
  Point D=project(a,b,g);
  return func0( abs(g-D) , abs(a-D) );
}
ldouble func(ldouble H,ldouble W){
  ldouble t=func0(H,W);
  ldouble ff = t*A+B*sqrt((W-t)*(W-t)+H*H );
  return ff;
} 
ldouble func2(Point a,Point b,Point g){
  Point D=project(a,b,g);
  return func( abs(g-D) , abs(a-D) );
}
 
void solve(){
  vector<Point> T;
  for(int i=0;i<n;i++){
    T.push_back(t[i]);
    if(i+1<n){
      ldouble tt = func02(t[i],t[i+1],g);
      Vector base=t[i+1]-t[i];      
      Point next =  t[i]+ base*( tt /abs(base) );
      if(!eq(next,t[i])&&!eq(next,t[i+1])
         && eq(abs(t[i]-next)+abs(t[i+1]-next),abs(t[i]-t[i+1]))
         )T.push_back(next);
    }
  }
   
  t=T;
  n=t.size();
  vector<ldouble> u(n);  
  u[0]=0;
  u[1]=abs(t[0]-t[1])*A;
  for(int i=2;i<n;i++){
    u[i]=u[i-1]+abs(t[i]-t[i-1])*A;
    for(int j=1;j<i;j++){
      u[i]=min(u[i],u[j-1]+func2(t[j-1],t[j],t[i]));
      u[i]=min(u[i],u[j-1]+func2(t[i],t[i-1],t[j-1]));
    }
  }
  for(int i=0;i+1<n;i++){
    ldouble na = u[i]+func2(t[i],t[i+1],g);
    ans=min(ans,na);
  }
}
 
int main(){
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  while(1){
    vector<Point> nt;
    cin>>n;
    if(n==0)break;
    t.clear();t.resize(n);
    for(int i=0;i<n;i++)cin>>t[i].x>>t[i].y;
    cin>>A>>B>>s.x>>s.y>>g.x>>g.y;
    int flg=0,f=-1;
    for(int i=0;i<n;i++){
      int j=(i+1)%n;      
      if(eq(s,t[i]))flg=1;
      if(eq( abs(s-t[i])+abs(s-t[j]) , abs(t[i]-t[j]) )){
        f=j;
        break;
      }
    }
    if(flg==0)nt.push_back(s);
    else f=(f+n-1)%n;
    for(int j=0;j<n;j++)nt.push_back(t[(f+j)%n]);
    n=nt.size();
    t=nt;
    ans=abs(s-g)*B;
    solve();
    reverse(t.begin()+1,t.end());
    solve();
    double ans2=ans;
    printf("%.14f\n",ans2);
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 1312
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;

typedef long double ldouble;

const ldouble eps = 0.000000001;

bool eq(ldouble a,ldouble b){
  return (-eps<a-b && a-b<eps);
}


struct Point{
  ldouble x,y;
  Point operator + (const Point p)const{
    return (Point){x+p.x,y+p.y};
  }
  Point operator - (const Point p)const{
    return (Point){x-p.x,y-p.y};
  }
  Point operator * (const ldouble r)const{
    return (Point){x*r,y*r};
  }
};
bool eq(Point a,Point b){
  return ( eq(a.x,b.x) && eq(a.y,b.y) );
}

typedef Point Vector;

ldouble dot(Vector a,Vector b){
  return a.x*b.x+a.y*b.y;
}

ldouble cross(Vector a,Vector b){
  return a.x*b.y-b.x*a.y;
}
ldouble norm(Vector v){
  return dot(v,v);
}

ldouble abs(Vector v){
  return sqrt(norm(v));
}


Point project(Point a,Point b,Point p){
  Point base=b-a;
  ldouble r=dot(p-a,base)/norm(base);
  return a+base*r;
}

ldouble calc(ldouble a,ldouble b,ldouble c){
  return (-b + sqrt(b*b-4.0*a*c))/ (2.0*a);
}



int n;
ldouble A,B;
vector<Point> t;
Point s,g;
ldouble ans;

ldouble func0(double H,double W){
  ldouble a=1.0;
  ldouble b=-2.0*W;
  ldouble c=W*W-(A*A*H*H)/(B*B-A*A);
  if(b*b-4.0*a*c<0)return min(H*B+W*A, sqrt(H*H+W*W)*B);
  ldouble t = (-b+sqrt(b*b-4.0*a*c))/(2.0*a);
  if(t>W){
    t=(-b-sqrt(b*b-4.0*a*c))/(2.0*a);
    if(t<0)return min(H*B+W*A, sqrt(H*H+W*W)*B);
  }
  return t;
}
ldouble func02(Point a,Point b,Point g){
  Point D=project(a,b,g);
  return func0( abs(g-D) , abs(a-D) );
}

ldouble func(ldouble H,ldouble W){
  ldouble a=1.0;
  ldouble b=-2.0*W;
  ldouble c=W*W-(A*A*H*H)/(B*B-A*A);
  if(b*b-4.0*a*c<0)return min(H*B+W*A, sqrt(H*H+W*W)*B);
  ldouble t = (-b+sqrt(b*b-4.0*a*c))/(2.0*a);
  if(t>W){
    t=(-b-sqrt(b*b-4.0*a*c))/(2.0*a);
    if(t<0)return min(H*B+W*A, sqrt(H*H+W*W)*B);
  }
  ldouble ff = t*A+B*sqrt((W-t)*(W-t)+H*H );
  return ff;
}

ldouble func2(Point a,Point b,Point g){
  Point D=project(a,b,g);
  return func( abs(g-D) , abs(a-D) );
}

void solve(){


  vector<Point> T;

  for(int i=0;i<n;i++){
    T.push_back(t[i]);
    if(i+1<n){
      ldouble tt = func02(t[i],t[i+1],g);
      Vector base=t[i+1]-t[i];      
      Point next =  t[i]+ base*( tt /abs(base) );
      if(!eq(next,t[i])&&!eq(next,t[i+1])
         && eq(abs(t[i]-next)+abs(t[i+1]-next),abs(t[i]-t[i+1]))
         )T.push_back(next);
    }
  }
  
  t=T;
  n=t.size();
  vector<ldouble> u(n);  
  u[0]=0;
  u[1]=abs(t[0]-t[1])*A;

  for(int i=2;i<n;i++){
    u[i]=u[i-1]+abs(t[i]-t[i-1])*A;
    for(int j=1;j<i;j++){
      u[i]=min(u[i],u[j-1]+func2(t[j-1],t[j],t[i]));
      u[i]=min(u[i],u[j-1]+func2(t[i],t[i-1],t[j-1]));
    }
  }
  for(int i=0;i+1<n;i++){
    /*
    cout<<i<<endl;
    cout<<(int)t[i].x<<' '<<(int)t[i].y<<endl;
    cout<<(int)t[i+1].x<<' '<<(int)t[i+1].y<<endl;
    cout<<(double)u[i]<<' '<<(double)u[i+1]<<endl;    
    cout<<(double)abs(t[i+1]-t[i])*(double)A<<endl;
    cout<<endl;
    */
    ldouble na = u[i]+func2(t[i],t[i+1],g);
    ans=min(ans,na);
  }

}

int main(){  
  while(1){
    vector<Point> nt;
    cin>>n;
    if(n==0)break;
    t.clear();t.resize(n);
    for(int i=0;i<n;i++)cin>>t[i].x>>t[i].y;
    cin>>A>>B>>s.x>>s.y>>g.x>>g.y;

    int flg=0,f=-1;
    for(int i=0;i<n;i++){
      int j=(i+1)%n;      
      if(eq(s,t[i]))flg=1;
      if(eq( abs(s-t[i])+abs(s-t[j]) , abs(t[i]-t[j]) )){
        f=j;
        break;
      }
    }
    
    if(flg==0)nt.push_back(s);
    else f=(f+n-1)%n;
    for(int j=0;j<n;j++)nt.push_back(t[(f+j)%n]);
    n=nt.size();
    t=nt;
    ans=abs(s-g)*B;
    solve();
    reverse(t.begin()+1,t.end());
    solve();
    double ans2=ans;
    printf("%.14f\n",ans2);
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 1288
final_rank: 2