#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>

using namespace std;

const double EPS = 1e-8;
const double INF = 1e12;

class Node{
public:
	int aPos, bPos, h; double c;
	Node(int aPos, int bPos, int h, double c) : aPos(aPos), bPos(bPos), h(h), c(c) {}
	bool operator < (const Node &nd) const { return c > nd.c; }
};

int main(){
	int n;
	int x[100], y[100];
	int h[1001];
	double len[100];
	static double dist[99][99][99];
	while(cin >> n, n){
		double res = 0.0;
		vector<int> hList;
		for(int i=0;i<n;i++){
			cin >> x[i] >> y[i];
			hList.push_back(y[i]);
		}
		while(n-2>=0 && y[n-2] == 0){
			res += x[n-1]-x[n-2];
			n--;
		}
		int s = 0;
		while(s+1<n && y[s+1] == 0){
			res += x[s+1]-x[s];
			s++;
		}
		if(n==1){
			printf("%.3lf\n", res);
			continue;
		}
		for(int i=0;i<n-1;i++)
			for(int j=0;j<n-1;j++)
				for(int k=0;k<n-1;k++) dist[i][j][k] = INF;
		for(int i=0;i+1<n;i++)
			len[i] = hypot(x[i+1]-x[i], y[i+1]-y[i]);
		sort(hList.begin(), hList.end());
		hList.erase(unique(hList.begin(), hList.end()), hList.end());
		for(int i=0;i<hList.size();i++) h[hList[i]] = i;
		priority_queue<Node> qu; qu.push(Node(s, n-2, h[0], res));
		dist[s][n-2][h[0]] = res;
		res = INF;
		while(!qu.empty()){
			Node nd = qu.top(); qu.pop();
			int aPos = nd.aPos, bPos = nd.bPos, hIdx = nd.h;
			int hCur = hList[hIdx];
			if(aPos == bPos){
				printf("%.3lf\n", dist[aPos][bPos][hIdx]);
				break;
			}

			if(dist[aPos][bPos][hIdx]+EPS < nd.c) continue;

			// ¯¶³ÌÚ®
			if(y[aPos] == hCur && y[aPos] == y[aPos+1]){
				if(dist[aPos+1][bPos][hIdx] > nd.c+len[aPos]+EPS){
					dist[aPos+1][bPos][hIdx] = nd.c+len[aPos];
					qu.push(Node(aPos+1, bPos, hIdx, dist[aPos+1][bPos][hIdx])); 
				}
			}
			if(aPos-1 >= s && y[aPos] == hCur && y[aPos] == y[aPos-1]){
				if(dist[aPos-1][bPos][hIdx] > nd.c+len[aPos-1]+EPS){
					dist[aPos-1][bPos][hIdx] = nd.c+len[aPos-1];
					qu.push(Node(aPos-1, bPos, hIdx, dist[aPos-1][bPos][hIdx])); 
				}
			}
			if(y[bPos] == hCur && y[bPos] == y[bPos-1]){
				if(dist[aPos][bPos-1][hIdx] > nd.c+len[bPos-1]+EPS){
					dist[aPos][bPos-1][hIdx] = nd.c+len[bPos-1];
					qu.push(Node(aPos, bPos-1, hIdx, dist[aPos][bPos-1][hIdx])); 
				}
			}
			if(bPos+1 < n-1 && y[bPos] == hCur && y[bPos] == y[bPos+1]){
				if(dist[aPos][bPos+1][hIdx] > nd.c+len[bPos]+EPS){
					dist[aPos][bPos+1][hIdx] = nd.c+len[bPos];
					qu.push(Node(aPos, bPos+1, hIdx, dist[aPos][bPos+1][hIdx])); 
				}
			}
			int aBack = aPos - (y[aPos] == hCur);
			int bBack = bPos - (y[bPos] == hCur);
			// A:OiCB:ãÞ
			if((y[aPos+1] > hCur && y[bBack] > hCur) || (y[aPos+1] < hCur && y[bBack] < hCur)){
				int hNext = y[aPos+1] > hCur ? min(y[aPos+1], y[bBack]) : max(y[aPos+1], y[bBack]);
				int aNext = aPos + (hNext == y[aPos+1]);
				double aLen = len[aPos]*abs(hNext-hCur)/abs(y[aPos]-y[aPos+1]);
				double bLen = len[bBack]*abs(hNext-hCur)/abs(y[bBack]-y[bBack+1]);
				if(dist[aNext][bBack][h[hNext]] > nd.c+aLen+bLen+EPS){
					dist[aNext][bBack][h[hNext]] = nd.c+aLen+bLen;
					qu.push(Node(aNext, bBack, h[hNext], dist[aNext][bBack][h[hNext]]));
				}
			}
			// A:Oi, B:Oi
			if((y[aPos+1] > hCur && y[bPos+1] > hCur) || (y[aPos+1] < hCur && y[bPos+1] < hCur)){
				int hNext = y[aPos+1] > hCur ? min(y[aPos+1], y[bPos+1]) : max(y[aPos+1], y[bPos+1]);
				int aNext = aPos + (hNext == y[aPos+1]);
				int bNext = bPos + (bPos+1 != n-1 && hNext == y[bPos+1]);
				double aLen = len[aPos]*abs(hNext-hCur)/abs(y[aPos]-y[aPos+1]);
				double bLen = len[bPos]*abs(hNext-hCur)/abs(y[bPos]-y[bPos+1]);
				if(dist[aNext][bNext][h[hNext]] > nd.c+aLen+bLen+EPS){
					dist[aNext][bNext][h[hNext]] = nd.c+aLen+bLen;
					qu.push(Node(aNext, bNext, h[hNext], dist[aNext][bNext][h[hNext]]));
				}
			}
			// A:ãÞ, B:Oi
			if(aBack >= s && ((y[aBack] > hCur && y[bPos+1] > hCur) || (y[aBack] < hCur && y[bPos+1] < hCur))){
				int hNext = y[aBack] > hCur ? min(y[aBack], y[bPos+1]) : max(y[aBack], y[bPos+1]);
				int bNext = bPos + (bPos+1 != n-1 && hNext == y[bPos+1]);
				double aLen = len[aBack]*abs(hNext-hCur)/abs(y[aBack]-y[aBack+1]);
				double bLen = len[bPos]*abs(hNext-hCur)/abs(y[bPos]-y[bPos+1]);
				if(dist[aBack][bNext][h[hNext]] > nd.c+aLen+bLen+EPS){
					dist[aBack][bNext][h[hNext]] = nd.c+aLen+bLen;
					qu.push(Node(aBack, bNext, h[hNext], dist[aBack][bNext][h[hNext]]));
				}
			}
			// A:ãÞ, B:ãÞ
			if(aBack >= s && ((y[aBack] > hCur && y[bBack] > hCur) || (y[aBack] < hCur && y[bBack] < hCur))){
				int hNext = y[aBack] > hCur ? min(y[aBack], y[bBack]) : max(y[aBack], y[bBack]);
				double aLen = len[aBack]*abs(hNext-hCur)/abs(y[aBack]-y[aBack+1]);
				double bLen = len[bBack]*abs(hNext-hCur)/abs(y[bBack]-y[bBack+1]);
				if(dist[aBack][bBack][h[hNext]] > nd.c+aLen+bLen+EPS){
					dist[aBack][bBack][h[hNext]] = nd.c+aLen+bLen;
					qu.push(Node(aBack, bBack, h[hNext], dist[aBack][bBack][h[hNext]]));
				}
			}
		}
	}
}

Measured memory_bytes: 8548