#include #include #include #include #include #include #define EQ(x,y) (abs((x) - (y)) <= EPS) using namespace std; const double EPS = 1e-12; const double WIDTH = 1e-04; struct cand_t { int p; double d; public: cand_t(int p, double d) : p(p), d(d) { } cand_t(void) { } public: bool operator <(const cand_t &other) const { if(!EQ(d, other.d)) return d > other.d; return p < other.p; } }; complex N(const complex &z) { return z / abs(z); } bool cross(const complex &z1, const complex &z2, const complex &z3, const complex &z4) { complex w3 = (z3 - z1) / (z2 - z1); complex w4 = (z4 - z1) / (z2 - z1); if(imag(w3) > +EPS && imag(w4) > +EPS) return false; if(imag(w3) < -EPS && imag(w4) < -EPS) return false; double kp = imag(w3 * conj(w4) - w4 * conj(w3)); double kq = 2.0 * imag(w3 - w4); if(EQ(kq, 0)) return false; double k = kp / kq; if(k < 0 - EPS || k > 1 + EPS) return false; return true; } int main(void) { ifstream cin("hedge.in"); int n; while(cin >> n, n) { vector< complex > z(n); for(int i = 0; i < n; i++) { double xi, yi; cin >> xi >> yi; z[i] = complex(xi, yi); } vector< complex > w; for(int i = 0; i < n; i++) { if(i == 0) { complex wplus = N(z[0] - z[1]); wplus *= WIDTH; w.push_back(z[i] + wplus); } else if(i == n - 1) { complex wplus = N(z[n-1] - z[n-2]); wplus *= WIDTH; w.push_back(z[i] + wplus); } else { complex zM = z[i-1] - z[i]; complex zP = z[i+1] - z[i]; complex wplus = N(zM) + N(zP); if(EQ(imag(zP / zM), 0.0)) wplus *= complex(0.0, 1.0); wplus *= WIDTH; w.push_back(z[i] + wplus); w.push_back(z[i] - wplus); } } int nv = w.size(); vector< vector > adj(nv, vector(nv, HUGE_VAL)); int src = 0; int dst = nv - 1; for(int i = 0; i < nv; i++) { for(int j = i + 1; j < nv; j++) { bool flag = false; for(int k = 1; k < n; k++) flag |= cross(w[i], w[j], z[k - 1], z[k]); if(!flag) { adj[i][j] = abs(z[(i+1)/2] - z[(j+1)/2]); adj[j][i] = adj[i][j]; } } } priority_queue cue; cue.push(cand_t(src, 0)); vector dis(nv, HUGE_VAL); while(!cue.empty()) { cand_t cand = cue.top(); cue.pop(); if(dis[cand.p] != HUGE_VAL) continue; dis[cand.p] = cand.d; if(cand.p == dst) break; for(int i = 0; i < nv; i++) { if(dis[i] == HUGE_VAL && adj[cand.p][i] != HUGE_VAL) cue.push(cand_t(i, cand.d + adj[cand.p][i])); } } cout << setprecision(6) << fixed << dis[dst] << endl; } }