#include <iostream>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <memory>
#include <cstring>
#include <cassert>
#include <numeric>
#include <sstream>
#include <complex>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
#include <unordered_map>
#include <unordered_set>
using namespace std;

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

template <typename T, typename E>
ostream &operator<<(std::ostream &os, const std::pair<T, E> &p){
  return os << "(" << p.first << ", " << p.second << ")";
}

typedef long long ll;

const int max_n = 110;
const double eps = 1e-9;
const double inf = 1e10;
int n;
double dist[max_n][max_n][3][3];
double xs[max_n];
double ys[max_n];

typedef complex<double> xy_t;

inline bool equal(double a, double b){
  return abs(a - b) < eps;
}


xy_t get_point(int i, double y){
  if (y < min(ys[i], ys[i + 1]) - eps) return xy_t(inf, inf);
  if (y > max(ys[i], ys[i + 1]) + eps) return xy_t(inf, inf);
  double x = xs[i] + (xs[i + 1] - xs[i]) * (y - ys[i]) / (ys[i + 1] - ys[i]);
  return xy_t(x, y);
}

int main(){
  ios::sync_with_stdio(false);
  
  while (cin >> n && n){
    REP(i, n) cin >> xs[i] >> ys[i];

    fill(&dist[0][0][0][0], &dist[0][0][0][0] + max_n * max_n * 9, inf);

    dist[0][n - 2][0][1] = 0;
    typedef tuple<double, int, int, int, int > state;
    priority_queue<state, vector<state>, greater<state> > que;
    que.push(make_tuple(0, 0, n - 2, 0, 1));

    double res = -1;
    while (!que.empty()){
      double c = get<0>(que.top());
      int x1 = get<1>(que.top());
      int x2 = get<2>(que.top());
      int s1 = get<3>(que.top());
      int s2 = get<4>(que.top()); que.pop();
      
      double yc = s1 != 2 ? ys[x1 + s1] : ys[x2 + s2];
      xy_t pc1 = s1 == 2 ? get_point(x1, yc) : xy_t(xs[x1 + s1], ys[x1 + s1]);
      xy_t pc2 = s2 == 2 ? get_point(x2, yc) : xy_t(xs[x2 + s2], ys[x2 + s2]);
      
      // cout << pc1 << " " << pc2 << " " << x1 << "  " << x2 << " " << c << endl;
      if (abs(pc1 - pc2) < eps){
        res = c;
        break;
      }
      
      if (c > dist[x1][x2][s1][s2] + eps){
        continue;
      }
      
      if (c < dist[x2][x1][s2][s1] - eps){
        dist[x2][x1][s2][s1] = c;
        que.push(make_tuple(c, x2, x1, s2, s1));
      }

      if (x1 > 0 && s1 == 0 && c < dist[x1 - 1][x2][1][s2] - eps){
        dist[x1 - 1][x2][1][s2] = c;
        que.push(make_tuple(c, x1 - 1, x2, 1, s2));
      }

      if (x1 < n - 2 && s1 == 1 && c < dist[x1 + 1][x2][0][s2] - eps){
        dist[x1 + 1][x2][0][s2] = c;
        que.push(make_tuple(c, x1 + 1, x2, 0, s2));
      }
      
      xy_t p01 = xy_t(xs[x1 + 0], ys[x1 + 0]);
      xy_t p11 = xy_t(xs[x1 + 1], ys[x1 + 1]);
      xy_t p02 = get_point(x2, p01.imag());
      xy_t p12 = get_point(x2, p11.imag());
      int  ns0 = 2;
      int  ns1 = 2;

      if (equal(ys[x2], ys[x2 + 1])){
        if (equal(p01.imag(), ys[x2])){
          p02 = pc2;
          ns0 = s2;
        }
        
        if (equal(p11.imag(), ys[x2])){
          p12 = pc2;
          ns1 = s2;
        }
      }
      
      double c0 = c + abs(pc1 - p01) + abs(pc2 - p02);
      double c1 = c + abs(pc1 - p11) + abs(pc2 - p12);
      
      // cout << c0 << " " << c1 << " " << p01 << " " << p11 << " " << p02 << " " << p12 << endl;
      
      if (c0 < dist[x1][x2][0][ns0] - eps){
        // cout << c0 << endl;
        dist[x1][x2][0][ns0] = c0;
        que.push(make_tuple(c0, x1, x2, 0, ns0));
      }

            if (c1 < dist[x1][x2][1][ns1] - eps){
        dist[x1][x2][1][ns1] = c1;
        que.push(make_tuple(c1, x1, x2, 1, ns1));
      }
    }
    printf("%.20lf\n", res);
    
  }
  
  return 0;
}

Measured memory_bytes: 2164