Problem:
Lifeguard in the Pool

プールの監視員

English text is not available in this practice contest.

Horton Moore はプールの監視員として働いている．彼が見回りのためにプールの縁を歩いていたところ，プールの中で一人の少女がおぼれていることに気づいた．もちろん，彼は直ちに救助に向かわなければならない．しかも，少女の身に何かあっては大変であるから，少しでも早く少女のもとにたどり着きたい．

あなたの仕事は，プールの形状（頂点数が 3〜10 の凸多角形），地上および水中における監視員の単位距離あたりの移動時間，そして監視員と少女の初期位置が与えられたときに，監視員が少女のところに到着するまでにかかる最短の時間を求めるプログラムを書くことである．

Input

入力は複数のデータセットの並びからなる．入力の終わりは 1 つの 0 だけを含む行によって示される．

各データセットは次の形式になっている．

n

x1 y1 x2 y2 ... xn yn

tg

tw

xs ys

xt yt

それぞれの記号の意味は次のとおりである．

n は凸多角形をしたプールの頂点数を示す．これは 3 以上 10 以下の整数である．

(xi, yi) はプールの 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

Solution in C++ (judge verdict: Wrong Answer)

#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;
            }
        }
        T = 10;
        hack = false;
        solve();
        T = 60;
        hack = true;
        double result = solve();
        cout<<fixed<<result<<endl;
    }
    return 0;
}