#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <set>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

#include <complex>
typedef complex<double> Point;
namespace std {
  bool operator<(const Point &lhs, const Point &rhs) {
    return lhs.real() < rhs.real();
  }
}

struct Line : public vector<Point> {
  Line() {;}
  Line(Point a, Point b) { push_back(a); push_back(b); }
};

int n;
Point points[1000];

inline double cross(const Point &a, const Point &b) {
  return imag(conj(a) * b);
}
inline double dot(const Point &a, const Point &b) {
  return real(conj(a) * b);
}
inline int ccw(Point a, Point b, Point c) {
  b -= a; c -= a;
  if (cross(b, c) > 0) { return 1; }
  if (cross(b, c) < 0) { return -1; }
  if (dot(b, c) < 0) { return 2; }
  if (norm(b) < norm(c)) { return -2; }
}

bool intersectLS(const Line &l, const Line &s) {
  return cross(l[1] - l[0], s[0] - l[0]) *
         cross(l[1] - l[0], s[1] - l[0]) < EPS;
}

inline bool intersectSP(const Line &s, const Point &p) {
  return abs(s[0] - p) + abs(s[1] - p) - abs(s[0] - s[1]) < EPS;
}

Point crosspointSS(const Line &l, const Line &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) {
    if (intersectSP(l, m[0])) { return m[0]; }
    if (intersectSP(l, m[1])) { return m[1]; }
    if (intersectSP(m, l[0])) { return l[0]; }
    if (intersectSP(m, l[1])) { return l[1]; }
    assert(false);
    return m[0];
  }
  if (abs(A) < EPS) { assert(false); }
  return m[0] + B / A * (m[1] - m[0]);
}

struct Edge {
  int from;
  int to;
  double cost;
  Edge() {;}
  Edge(int from, int to, double cost) : from(from), to(to), cost(cost) {;}
  bool operator<(const Edge &rhs) const {
    return cost > rhs.cost;
  }
};

vector<Edge> edges[20010];
int height[20010];
set<pair<int, int> > visit;
map<pair<int, int>, double>  dist;

int main() {
  while (scanf("%d", &n), n) {
    REP(i, 20010) { edges[i].clear(); }
    visit.clear();
    dist.clear();
    set<int> ys;
    set<Point> ps;
    REP(i, n) {
      int x, y;
      scanf("%d %d", &x, &y);
      points[i] = Point(x, y);
      ys.insert(y);
    }
    int head = 1;
    FOR(i, 1, n - 1) {
      if (points[i].imag() == points[i - 1].imag() && points[i].imag() == points[i + 1].imag()) {
        continue;
      }
      points[head++] = points[i];
    }
    points[head++] = points[n - 1];
    n = head;
    REP(i, n - 1) {
      Line line(points[i], points[i + 1]);
      if (line[0].imag() == line[1].imag()) {
        for (double x = line[0].real(); x <= line[1].real() + EPS; x += 1.0) {
          ps.insert(Point(x, line[0].imag()));
        }
        ps.insert(Point((points[i].real() + points[i + 1].real()) / 2.0, points[i].imag()));
      } else {
        ps.insert(points[i]);
        ps.insert(points[i + 1]);
        FORIT(it, ys) {
          Line horizon = Line(Point(-10, *it), Point(1010, *it));
          if (intersectLS(horizon, line)) {
            ps.insert(crosspointSS(horizon, line));
          }
        }
      }
    }
    int m = ps.size();
    MEMSET(height, 0);
    int index = 1;
    Point prev = *ps.begin();
    height[0] = prev.imag();
    edges[0].push_back(Edge(0, 0, 0));
    FORIT(it, ps) {
      if (it == ps.begin()) { it++; }
      double cost = abs(*it - prev);
      edges[index].push_back(Edge(index, index - 1, cost));
      edges[index - 1].push_back(Edge(index - 1, index, cost));
      edges[index].push_back(Edge(index, index, 0));
      height[index] = it->imag() + 0.1;
      prev = *it;
      index++;
    }
    priority_queue<Edge> que;
    que.push(Edge(0, m - 1, 0));
    while (!que.empty()) {
      int left = que.top().from;
      int right = que.top().to;
      double cost = que.top().cost;
      que.pop();
      if (visit.count(pair<int, int>(left, right))) { continue; }
      visit.insert(pair<int, int>(left, right));
      if (left == right) {
        printf("%.8f\n", cost);
        break;
      }
      FORIT(it1, edges[left]) {
        FORIT(it2, edges[right]) {
          int nleft = it1->to;
          int nright = it2->to;
          double ncost = it1->cost + it2->cost + cost;
          if (visit.count(pair<int, int>(nleft, nright))) { continue; }
          if (height[nleft] != height[nright]) { continue; }
          //if (dist[nleft][nright] <= ncost) { continue; }
          //dist[nleft][nright] = ncost;
          que.push(Edge(nleft, nright, ncost));
        }
      }
    }
  }
}

Measured memory_bytes: 6320