#include <iostream>
#include <complex>
#include <sstream>
#include <string>
#include <algorithm>
#include <deque>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <vector>
#include <set>
#include <limits>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;
#define REP(i, j) for(int i = 0; i < (int)(j); ++i)
#define FOR(i, j, k) for(int i = (int)(j); i < (int)(k); ++i)
#define SORT(v) sort((v).begin(), (v).end())
#define REVERSE(v) reverse((v).begin(), (v).end())
const double EPS = 1e-12;
const double INF = 1e12;
#define EQ(a,b) (abs((a)-(b)) < EPS)
typedef complex<double> P;
const int MAX_N = 105;
#define DEBUG

struct C {
  P p; double r;
  C(const P &p, double r) : p(p), r(r) { }
};

struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
};

vector<P> crosspointCC(const C &c1, const C &c2){
  vector<P> res;
  double d = abs(c1.p - c2.p);
  double rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
  double dfr = c1.r * c1.r - rc * rc;
  if(EQ(dfr, 0.0)) dfr = 0.0;
  else if(dfr < 0.0) return res;
  double rs = sqrt(dfr);

  P diff = (c2.p - c1.p) / d;
  res.push_back(c1.p + diff * P(rc, rs));
  res.push_back(c1.p + diff * P(rc, -rs));
  return res;
}

double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}

double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}

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

bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
    ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}

double dist(P &a, P &b, vector<L> &ls, int s, int t){
  L l = L(a, b);
  FOR(i, s, t) if(!intersectSS(l, ls[i])) return INF;
  return abs(a - b);
}

int main() {
  int N;
  while(cin >>N && N){
    vector<P> ps;
    vector<L> ls;
    int bx, by, br, x, y, r;
    scanf("%d %d %d", &bx, &by, &br);
    ps.push_back(P(bx, by));
    FOR(i, 1, N){
      scanf("%d %d %d", &x, &y, &r);
      vector<P> cs = crosspointCC(C(P(bx, by), br), C(P(x, y), r));
      REP(j, cs.size()) ps.push_back(cs[j]);
      ls.push_back(L(cs[0], cs[1]));
      bx = x;
      by = y;
      br = r;
    }
    ps.push_back(P(bx, by));
    int psize = ps.size();
    vector< vector<double> > d(psize, vector<double>(psize, INF));
    REP(i, psize) FOR(j, i + 1, psize) d[i][j] = d[j][i] = dist(ps[i], ps[j], ls, (i + 1 == psize ? (int)ls.size() : (i - 1) / 2), (j + 1 == psize ? (int)ls.size() : (j - 1) / 2 + 1));
    vector<double> dp(psize, INF);
    dp[0] = 0.0;
    REP(i, psize){
      if(dp[i] == INF) continue;
      FOR(j, i + 1, psize){
        if(d[i][j] == INF) continue;
        dp[j] = min(dp[j], dp[i] + d[i][j]);
      }
    }
    printf("%.6lf\n", dp[psize - 1]);
  }
  return 0;
}