#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<complex>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
using namespace std;
typedef long long  ll;
typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 1000000007;
typedef double ld;
typedef complex<ld> Point;
const ll INF = mod * mod;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
const ld eps = 1e-8;
const ld pi = acos(-1.0);
typedef pair<ld, ld> LDP;
typedef pair<ll, ll> LP;
typedef vector<int> vec;

typedef pair<ld,P> speP;

bool eq(ld a, ld b) {
	return abs(a - b) < eps;
}

int n;
void solve() {
	vector<int> x(n),y(n);
	rep(i, n)cin >> x[i] >> y[i];
	vector<int>vy;
	rep(i, n)vy.push_back(y[i]);
	sort(vy.begin(), vy.end());
	vy.erase(unique(vy.begin(), vy.end()), vy.end());
	vector<LDP> z;
	rep(i, n)z.push_back({ x[i],y[i] });
	rep(i, n - 1) {
		ld dy = y[i + 1] - y[i];
		ld dx = x[i + 1] - x[i];
		int ly = min(y[i], y[i + 1]);
		int ry = max(y[i], y[i + 1]);
		rep(j, vy.size()) {
			if (ly < vy[j] && vy[j] < ry) {
				ld dis = abs(vy[j] - y[i]);
				ld nx = x[i] + dx * dis / abs(dy);
				z.push_back({ nx,vy[j] });
			}
		}
	}
	sort(z.begin(), z.end());
	int m = z.size();
	vector<ld> len(m-1);
	rep(i, m - 1) {
		ld dy = z[i + 1].second - z[i].second;
		ld dx = z[i + 1].first - z[i].first;
		len[i] = sqrt(dx*dx + dy * dy);
	}
	map<P, ld> dist;
	map<P, bool> vis;
	priority_queue<speP, vector<speP>, greater<speP>> q;
	dist[{0, m - 1}] = 0;
	q.push({ 0,{0,m - 1} });
	vis[{0, m - 1}] = true;
	ld ans = mod;
	while (!q.empty()) {
		speP p = q.top(); q.pop();
		int l = p.second.first, r = p.second.second;
		if (r == l + 1) {
			ans = min(ans, p.first + len[l]);
			continue;
		}
		if (l == r) {
			ans = min(ans, p.first);
			continue;
		}
		for (int i = -1; i <= 1; i +=2) {
			for (int j = -1; j <= 1; j += 2) {
				int nl = l + i, nr = r + j;
				if (nl < 0 || nr >= m||nl>nr)continue;
				if (eq(z[nl].second,z[nr].second)) {
					ld nd = p.first + len[min(nl,l)] + len[min(nr,r)];
					if (!vis[{nl, nr}]) {
						vis[{nl, nr}] = true;
						dist[{nl, nr}] = mod;
					}
					if (nd < dist[{nl, nr}]) {
						dist[{nl, nr}] = nd;
						q.push({ nd,{nl,nr} });
					}
				}
			}
		}
		if (l+1<=r&&eq(z[l].second, z[l + 1].second)) {
			int nl = l + 1, nr = r;
			ld nd = p.first + len[l];
			if (!vis[{nl, nr}]) {
				vis[{nl, nr}] = true;
				dist[{nl, nr}] = mod;
			}
			if (nd < dist[{nl, nr}]) {
				dist[{nl, nr}] = nd;
				q.push({ nd,{ nl,nr } });
			}
		}
		if (l > 0 && eq(z[l].second, z[l - 1].second)) {
			int nl = l - 1, nr = r;
			ld nd = p.first + len[l-1];
			if (!vis[{nl, nr}]) {
				vis[{nl, nr}] = true;
				dist[{nl, nr}] = mod;
			}
			if (nd < dist[{nl, nr}]) {
				dist[{nl, nr}] = nd;
				q.push({ nd,{ nl,nr } });
			}
		}
		if (r - 1 >= l && eq(z[r].second, z[r- 1].second)) {
			int nl = l, nr = r-1;
			ld nd = p.first + len[r-1];
			if (!vis[{nl, nr}]) {
				vis[{nl, nr}] = true;
				dist[{nl, nr}] = mod;
			}
			if (nd < dist[{nl, nr}]) {
				dist[{nl, nr}] = nd;
				q.push({ nd,{ nl,nr } });
			}
		}
		if (r + 1 < m && eq(z[r].second, z[r + 1].second)) {
			int nl = l, nr = r + 1;
			ld nd = p.first + len[r];
			if (!vis[{nl, nr}]) {
				vis[{nl, nr}] = true;
				dist[{nl, nr}] = mod;
			}
			if (nd < dist[{nl, nr}]) {
				dist[{nl, nr}] = nd;
				q.push({ nd,{ nl,nr } });
			}
		}
	}

	//cout << "ans is ";
	cout << ans << endl;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(5);
	while (cin >> n,n)solve();
	//solve();
	//stop
	return 0;
}



Measured memory_bytes: 8816