#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < n; i++)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pi;
typedef pair<int, double> pid;
typedef pair<double, int> pdi;
typedef pair<ll, ll> pl;

typedef double D;
typedef complex<D> P;
typedef pair<P, P> L;
typedef vector<P> VP;
const D EPS = 1e-9;
#define X real()
#define Y imag()
#define LE(n,m) ((n) < (m) + EPS)
#define GE(n,m) ((n) + EPS > (m))
#define EQ(n,m) (abs((n)-(m)) < EPS)

const ll mod = 1000000007;
const int inf = 1 << 30;
const ll linf = 1LL << 60;
const double PI = 3.14159265358979323846;

D dot(P a, P b) {
  return (conj(a)*b).X;
}

D cross(P a, P b) {
  return (conj(a)*b).Y;
}

int ccw(P a, P b, P c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}

P proj(P a1, P a2, P p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}

bool isecSS(P a1, P a2, P b1, P b2) {
  return ccw(a1, a2, b1)*ccw(a1, a2, b2) <= 0 &&
         ccw(b1, b2, a1)*ccw(b1, b2, a2) <= 0;
}

VP crosspointLC(P a1, P a2, P c, D r) {
  VP ps;
  P ft = proj(a1, a2, c);
  if (!GE(r*r, norm(ft-c))) return ps;

  P dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}

VP crosspointCC(P a, D ar, P b, D br) {
  VP ps;
  P ab = b-a;
  D d = abs(ab);
  D crL = (norm(ab) + ar*ar - br*br) / (2*d);
  if (EQ(d, 0) || ar < abs(crL)) return ps;

  P abN = ab * P(0, sqrt(ar*ar - crL*crL) / d);
  P cp = a + crL/d * ab;
  ps.push_back(cp + abN);
  if (!EQ(norm(abN), 0)) ps.push_back(cp - abN);
  return ps;
}

int n;
P p[100];
D r[100];
struct CP {
    P p;
    int i;
    double dis;
};
vector<CP> cps;
vector<pid> e[200];

void solve() {
    cps.clear();
    rep(i,200) e[i].clear();
    rep(i,n) {
        D x, y;
        cin >> x >> y >> r[i];
        p[i] = P(x, y);
    }
    {
        CP cp;
        cp.p = p[0];
        cp.i = 0;
        cp.dis = 0.0;
        cps.push_back(cp);
    }
    rep(i,n-1) {
        VP hoge = crosspointCC(p[i], r[i], p[i+1], r[i+1]);
        rep(j,hoge.size()) {
            CP cp;
            cp.p = hoge[j];
            cp.i = i+1;
            cp.dis = inf;
            cps.push_back(cp);
        }
    }
    {
        CP cp;
        cp.p = p[n-1];
        cp.i = n;
        cp.dis = inf;
        cps.push_back(cp);
    }
    rep(i,cps.size()) {
        for (int j = i+1; j < cps.size(); j++) {
            CP cp1 = cps[i];
            CP cp2 = cps[j];
            if (cp1.i == cp2.i) continue;
            bool ok = true;
            double pred = inf;
            for (int k = cp1.i; k < cp2.i; k++) {
                if (!isecSS(cp1.p, cp2.p, cps[2*k+1].p, cps[2*k+2].p)) {
                    ok = false;
                    break;
                }
            }
            if (!ok) continue;
            double dis = abs(cp1.p-cp2.p);
            //cerr << i << " " << j << " " << dis << endl;
            //cerr << i << " " << j << endl;
            e[i].push_back(pid(j, dis));
            e[j].push_back(pid(i, dis));
        }
    }
    priority_queue<pdi, vector<pdi>, greater<pdi>> pque;
    pque.push(pdi(0.0, 0));
    while (!pque.empty()) {
        pdi p = pque.top(); pque.pop();
        if (cps[p.second].dis+EPS < p.first) continue;
        rep(j,e[p.second].size()) {
            int to = e[p.second][j].first;
            double cost = e[p.second][j].second;
            if (cps[to].dis > cps[p.second].dis + cost) {
                cps[to].dis = cps[p.second].dis + cost;
                pque.push(pdi(cps[to].dis, to));
            }
        }
    }
    cout << cps[cps.size()-1].dis << endl;
}

int main() {
#ifndef LOCAL
    ios::sync_with_stdio(false);
    cin.tie(0);
#endif
    cout << fixed;
    cout.precision(20);
    cerr << fixed;
    cerr.precision(6);
#ifdef LOCAL
    //freopen("in.txt", "wt", stdout); //for tester
    freopen("in.txt", "rt", stdin);
#endif  
    while (cin >> n) {
        if (n == 0) break;
        solve();
    }
    //cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
    return 0;
}



Measured memory_bytes: 3468