//ACM-ICPC OB/OGの会 //模擬国内予選E問題解答 //牟田秀俊 #include #include #include using namespace std; typedef complex cd; //double 型複素数の型 typedef pair Point; //多角形の頂点を表す型 //cd 多角形の頂点 //double 0 番の頂点から多角形の辺を反時計回りに移動した時の距離 typedef pair Edge; //多角形の辺を表す型 //first → secondは反時計周り double tg, tw, fullLength, ratio; //tg 地上移動速度係数 //tw 水中移動速度係数 //fullLength 多角形の一周の長さ //ratio tg / sqrt(tw*tw - tg*tg)意味はスライド参照 cd src, dst; //src 監視員の座標 //dst 少女の座標 //p0 が原点に p1 が実数値が正となる実軸上になるように、 //target を平行移動&回転移動させる cd moveAndRotate(cd target, cd p0, cd p1){ return((target - p0) / ((p1 - p0) / abs(p1 - p0))); } //src から水中に入り e 上のどこかの点で浮上 //e 上を歩き、 //e 上のどこかの点から飛び込んで dst に至る最短時間を出力 double calMinimumOneEdgePath(Edge e){ cd p0 = e.second.first; cd p1 = e.first.first; cd srct = moveAndRotate(src, p0, p1); cd dstt = moveAndRotate(dst, p0, p1); p1 = moveAndRotate(p1, p0, p1); //timeWaterXpointVector vector > twxpv[2]; cd srcAndDst[] = {srct, dstt}; for(int i = 0; i < 2; i++){ cd point = srcAndDst[i]; twxpv[i].push_back(make_pair(tw * abs(point), 0.0)); twxpv[i].push_back(make_pair(tw * abs(point - p1), real(p1))); double sign[] = {1.0, -1.0}; for(int j = 0; j < 2; j++){ double xpoint = real(point) + sign[j] * ratio * imag(point); if(0 <= xpoint && xpoint <= real(p1)){ twxpv[i].push_back(make_pair(tw * abs(point - cd(xpoint, 0)), xpoint)); } } } double output = 10000000.0; for(int i = 0; i < twxpv[0].size(); i++){ for(int j = 0; j < twxpv[1].size(); j++){ output = min(output, twxpv[0][i].first + tg * abs(twxpv[0][i].second - twxpv[1][j].second) + twxpv[1][j].first); } } return(output); } //p0 から p1 まで多角形の周を反時計回りか時計回りに移動した場合の最短時間を出力 double vergeLength(Point p0, Point p1){ double len = abs(p0.second - p1.second); return(tg * min(len, fullLength - len)); } //水中の点 p から e のどちらかの端点(toFirstが真なら first)へ至る最短時間を出力 double calMinimumLengthPointOfEdge(cd p, Edge e, bool toFirst){ if(toFirst)e = make_pair(e.second, e.first); cd p0 = e.first.first; cd p1 = e.second.first; p = moveAndRotate(p, p0, p1); p1 = moveAndRotate(p1, p0, p1); double output = min(tw * abs(p - p1), tw * abs(p) + tg * real(p1)); double xpoint = real(p) + ratio * abs(imag(p)); if(0 <= xpoint && xpoint <= real(p1)){ output = min(output, tw * abs(p - cd(xpoint, 0)) + tg * (real(p1) - xpoint)); } return(output); } //src から esrc 上の辺で浮上して、 //多角形の周上を移動し、 //edst 上の辺から dst に至る最短時間を出力 double calMinimumTwoEdgePath(Edge esrc, Edge edst){ double lensrc0 = calMinimumLengthPointOfEdge(src, esrc, true); double lengnd0 = vergeLength(esrc.first, edst.second); double lendst0 = calMinimumLengthPointOfEdge(dst, edst, false); double len0 = lensrc0 + lengnd0 + lendst0; double lensrc1 = calMinimumLengthPointOfEdge(src, esrc, false); double lengnd1 = vergeLength(esrc.second, edst.first); double lendst1 = calMinimumLengthPointOfEdge(dst, edst, true); double len1 = lensrc1 + lengnd1 + lendst1; return(min(len0, len1)); } int main(void){ while(true){ //入力 int n; cin >> n; if(n == 0)break; double xpos[n], ypos[n], xs, ys, xd, yd; Edge edges[n]; for(int i = 0; i < n; i++){ cin >> xpos[i] >> ypos[i]; } cin >> tg >> tw >> xs >> ys >> xd >> yd; //多角形の構築等準備計算 src = cd(xs, ys); dst = cd(xd, yd); fullLength = 0.0; for(int i0 = 0; i0 < n; i0++){ int i1 = (i0 + 1) % n; cd cd0 = cd(xpos[i0], ypos[i0]); cd cd1 = cd(xpos[i1], ypos[i1]); Point p0 = make_pair(cd0, fullLength); Point p1 = make_pair(cd1, fullLength + abs(cd0 - cd1)); edges[i0] = make_pair(p0, p1); fullLength += abs(cd0 - cd1); } ratio = tg / sqrt(tw*tw - tg*tg); //最短時間計算 double answer = tw * abs(src - dst); for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ if(i == j)continue; answer = min(answer, calMinimumTwoEdgePath(edges[i], edges[j])); } } for(int i = 0; i < n; i++){ answer = min(answer, calMinimumOneEdgePath(edges[i])); } printf("%.20f\n", answer); } }