#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
//#include<cctype>
#include<climits>
#include<iostream>
#include<string>
#include<vector>
#include<map>
//#include<list>
#include<queue>
#include<deque>
#include<algorithm>
//#include<numeric>
#include<utility>
#include<complex>
//#include<memory>
#include<functional>
#include<cassert>

const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef complex<double> C;

double eps = 1e-9;

double add(double a, double b) {
    if (abs(a+b) < eps * (abs(a)+abs(b))) return 0;
    return a+b;
}

bool equal(double a, double b) {
    return add(a, -b) == 0;
}

struct P {
    double x, y;
    P() {}
    P(double x, double y) : x(x), y(y) {}
    P operator+(P p) const {return P(add(x, p.x), add(y, p.y));}
    P operator-(P p) const {return P(add(x, -p.x), add(y, -p.y));}
    P operator*(double d) const {return P(x*d, y*d);}
    double dot(P p) const {return add(x*p.x, y*p.y);} // ??????
    double det(P p) const {return add(x*p.y, -y*p.x);} // ??????
    double dist(P p) const {return sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));} // ?????¢
    bool operator<(const P& rhs) const {
        if (x != rhs.x) return x < rhs.x;
        return y < rhs.y;
    }
    bool operator==(const P& rhs) const {
        return equal(x, rhs.x) && equal(y, rhs.y);
    }
};

// ??????p1-p2?????????q???????????????????????????
// ????¢????
bool on_seg(P p1, P p2, P q) {
    return (p1-q).det(p2-q) == 0 && (p1-q).dot(p2-q) <= 0;
}

// ??´???p1-p2??¨??´???q1-q2?????????
// ????¢????
P intersection(P p1, P p2, P q1, P q2) {
    return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));
}

double square(double x) {return x*x;}

const int MAXN = 101;
const double INF = 1e18;
int n;
double x[MAXN], y[MAXN], r[MAXN];
double dp[MAXN][2];
P ps[MAXN][2];

bool ok(int from, int fromi, int to, int toi) {
    for (int i = from+1; i < to; i++) {
        P inter = intersection(ps[from][fromi], ps[to][toi], ps[i][0], ps[i][1]);
        if (on_seg(ps[i][0], ps[i][1], inter)) continue;
        else return false;
    }
    return true;
}

void solve() {
    ps[0][0].x = ps[0][1].x = x[0];
    ps[0][0].y = ps[0][1].y = y[0];
    ps[n][0].x = ps[n][1].x = x[n-1];
    ps[n][0].y = ps[n][1].y = y[n-1];
    for (int i = 0; i <= n; i++) for (int j = 0; j < 2; j++) {
        dp[i][j] = INF;
    }
    dp[0][0] = dp[0][1] = 0;
    for (int i = 0; i < n-1; i++) {
        double x1 = x[i+1] - x[i];
        double y1 = y[i+1] - y[i];
        double r1 = r[i], r2 = r[i+1];
        double a = (square(x1) + square(y1) + square(r1) - square(r2)) / 2;
        ps[i+1][0].x = (a*x1 + y1 * sqrt((square(x1) + square(y1)) * square(r1) - square(a))) / (square(x1) + square(y1)) + x[i];
        ps[i+1][1].x = (a*x1 - y1 * sqrt((square(x1) + square(y1)) * square(r1) - square(a))) / (square(x1) + square(y1)) + x[i];
        ps[i+1][0].y = (a*y1 - x1 * sqrt((square(x1) + square(y1)) * square(r1) - square(a))) / (square(x1) + square(y1)) + y[i];
        ps[i+1][1].y = (a*y1 + x1 * sqrt((square(x1) + square(y1)) * square(r1) - square(a))) / (square(x1) + square(y1)) + y[i];
    }
    //for (int i = 0; i <= n; i++) {
    //    cout << i << endl;
    //    cout << ps[i][0].x << "  " << ps[i][0].y << endl;
    //    cout << ps[i][1].x << "  " << ps[i][1].y << endl;
    //}
    for (int i = 0; i < n; i++) for (int j = 0; j < 2; j++) {
        for (int k = i+1; k <= n; k++) for (int l = 0; l < 2; l++) {
            if (ok(i, j, k, l)) {
                dp[k][l] = min(dp[k][l], dp[i][j] + ps[i][j].dist(ps[k][l]));
            }
        }
    }
    printf("%.15lf\n", dp[n][0]);
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    while (cin >> n) {
        if (n == 0) break;
        for (int i = 0; i < n; i++) {
            cin >> x[i] >> y[i] >> r[i];
        }
        solve();
    }
    return 0;
}

Measured memory_bytes: 1276