#include <iostream>
#include <vector>
#include <complex>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>

using namespace std;

bool isCrossed(complex<double> p1, complex<double> p2, complex<double> p3, complex<double> p4) {
    if ( ((p1.real() - p2.real()) * (p3.imag() - p1.imag()) + (p1.imag() - p2.imag()) * (p1.real() - p3.real())) *
            ((p1.real() - p2.real()) * (p4.imag() - p1.imag()) + (p1.imag() - p2.imag()) * (p1.real() - p4.real())) > 0)
        return false;
    return true;
}

int main() {
    int N = 0;
    while (cin>>N && N) {
        vector<pair<complex<double>, double> > circles(N);
        complex<double> centerize;
        for (int n = 0; n < N; n++) {
            int x,y,r;
            cin>>x>>y>>r;
            if (n == 0) {
                centerize = complex<double>(x,y);
                circles[n] = make_pair(complex<double>(0.0, 0.0), (double)r);
            }
            circles[n] = make_pair(complex<double>(x,y)-centerize, (double)r);
        }

        vector<complex<double> > vertices(2 * N);
        vertices[0] = circles[0].first;
        vertices[1] = circles[N-1].first;
        for (int n = 0; n < N-1; n++) {
            complex<double> v = circles[n+1].first - circles[n].first;
            double a = atan2(v.imag(), v.real());
            double theta = acos((norm(v) + circles[n].second*circles[n].second - circles[n+1].second*circles[n+1].second)
                / (2 * abs(v) * circles[n].second));
            vertices[2+2*n] = complex<double>(circles[n].second * cos(a+theta), circles[n].second * sin(a+theta)) + circles[n].first;
            vertices[3+2*n] = complex<double>(circles[n].second * cos(a-theta), circles[n].second * sin(a-theta)) + circles[n].first;
            /*
            double a = (v.real()*v.real()+v.imag()*v.imag()+circles[n].second*circles[n].second-circles[n+1].second*circles[n+1].second) / 2.0;
            double x1 = ( a*v.real() + v.imag()*sqrt((v.real()*v.real()+v.imag()*v.imag())*circles[n].second*circles[n].second-a*a) )
                            / (v.real()*v.real()+v.imag()*v.imag());
            double y1 = ( a*v.imag() - v.real()*sqrt((v.real()*v.real()+v.imag()*v.imag())*circles[n].second*circles[n].second-a*a) )
                            / (v.real()*v.real()+v.imag()*v.imag());
            double x2 = ( a*v.real() - v.imag()*sqrt((v.real()*v.real()+v.imag()*v.imag())*circles[n].second*circles[n].second-a*a) )
                            / (v.real()*v.real()+v.imag()*v.imag());
            double y2 = ( a*v.imag() + v.real()*sqrt((v.real()*v.real()+v.imag()*v.imag())*circles[n].second*circles[n].second-a*a) )
                            / (v.real()*v.real()+v.imag()*v.imag());
            vertices[2+2*n] = complex<double>(x1,y1);
            vertices[3+2*n] = complex<double>(x2,y2);*/
        }

        multimap<int, pair<int, double> > ds;
        for (int n = 0; n < N; n++) {
            for (int s = 0; s < 2; s++) {
                for (int i = n+1; i < N+1; i++) {
                    for (int t = 0; t < 2; t++) {
                        if (i != N) {
                            bool flag = true;
                            for (int u = n+1; u < i; u++) {
                                if (!(isCrossed(vertices[2*n+s], vertices[2*i+t], vertices[2*u], vertices[2*u+1]) &&
                                        isCrossed(vertices[2*u], vertices[2*u+1], vertices[2*n+s], vertices[2*i+t]))) {
                                    flag = false;
                                    break;
                                }
                            }
                            if (flag) ds.insert(make_pair(2*n+s, make_pair(2*i+t, (double)abs(vertices[2*i+t] - vertices[2*n+s]))));
                        } else {
                            bool flag = true;
                            for (int u = n+1; u < i; u++) {
                                if (!(isCrossed(vertices[2*n+s], vertices[1], vertices[2*u], vertices[2*u+1]) &&
                                        isCrossed(vertices[2*u], vertices[2*u+1], vertices[2*n+s], vertices[1]))) {
                                    flag = false;
                                    break;
                                }
                            }
                            if (flag) ds.insert(make_pair(2*n+s, make_pair(1, (double)abs(vertices[1] - vertices[2*n+s]))));
                            break;
                        }
                    }
                }
                if (n == 0) break;
            }
        }

        priority_queue<pair<double, int>, vector<pair<double, int> >, greater<pair<double, int> > > pqueue;
        double finalDs[1000] = {};
        for (int n = 0; n < N; n++) {
            finalDs[2*n] = -1.0;
            finalDs[2*n+1] = -1.0;
        }

        pqueue.push(make_pair(0.0, 0));
        while (!pqueue.empty()) {
            auto p = pqueue.top();
            pqueue.pop();
            if (finalDs[p.second] < 0.0) finalDs[p.second] = p.first;
            else continue;

            auto it = ds.lower_bound(p.second);
            auto last = ds.upper_bound(p.second);
            for (; it != last; it++) {
                pqueue.push(make_pair(p.first+it->second.second, it->second.first));
            }
        }
        cout<<fixed<<finalDs[1]<<endl;
    }
}

Measured memory_bytes: 3864