//void __(){
//    int xs,ys,xt,yt;
//    cin >> xs >> ys >> xt >> yt;
//    _(int,n);
//    _(vvi,circ,n,vi(3));
//    circ.pb({xs,ys,0});
//    circ.pb({xt,yt,0});
//    vvd cost(n+2,vd(n+2));
//    rep(i,n+2)
//        rep(j,n+2)
//            cost[i][j] = max(0.0,hypot(circ[i][0]-circ[j][0],circ[i][1]-circ[j][1])-circ[i][2]-circ[j][2]);
//
//    vd dist(n+2,INF);
//    vb visited(n+2);
//    dist[n] = 0;
//    priority_queue<pair<ld,int>> pq;
//    pq.push({0,n});
//    while(!pq.empty()){
//        ld tmp;
//        int u;
//        tie(tmp,u) = pq.top();
//        pq.pop();
//        if(visited[u])
//            continue;
//        visited[u] = true;
//        rep(i,n+2){
//            if(!visited[i] && dist[i] > dist[u]+cost[u][i]){
//                dist[i] = dist[u]+cost[u][i];
//                pq.push({-dist[i],i});
//            }
//        }
//    }
//    print dist[n+1];
//}
//
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <queue>
#include <cassert>
#include <vector>
#include <utility>
#include <iostream>
#include <string>
#define pb push_back
#define REP_ZERO_INT(i,r) for(int i = 0; i < r; ++i)
#define GET_REP_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define rep(...) GET_REP_MACRO(__VA_ARGS__,REP_ANY,REP_INT,REP_ZERO_INT)(__VA_ARGS__)
#define all(v) (v).begin(), (v).end()
#define sz(v) ll(v.size())
#define T1 template<typename T> static
using namespace std;
typedef long long ll;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef double ld;
typedef vector<ld> vd;
typedef vector<vd> vvd;
const ll INF = ll(2e18) + 666;
T1 ostream& operator<<(ostream& stream, const vector<T>& t);
T1 istream& read(T, T, istream& = cin);
T1 istream& operator>>(istream& stream, vector<T>& t){
    return read(all(t), stream);
}
T1 istream& read(T b, T e, istream& stream){
    for(T it = b; it != e; ++it)
        stream >> *it;
    return stream;
}
struct _print {
    string sep,end;
    bool space;
    ostream &stream;
    _print(string _sep=" ",string _end="\n",
            ostream &_stream = cout)
        : sep(_sep),end(_end),space(false),
            stream(_stream) {}
    ~_print() { stream << end; }
    template <typename T>
        _print &operator , (const T &t) {
            if (space) stream << sep;
            space = true;
            stream << t;
            return *this;
        }
};
#define print _print(),
#define INPUT_WITHOUT_INIT(type,name) type name; cin >> name
#define _IWI(type,name,...) type name(__VA_ARGS__); cin >> name
#define GET_INPUT_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,NAME,...) NAME
#define _(...) GET_INPUT_MACRO(__VA_ARGS__,_IWI,_IWI,_IWI,_IWI,_IWI,_IWI,INPUT_WITHOUT_INIT)(__VA_ARGS__)
void __(){
    int xs,ys,xt,yt;
    cin >> xs >> ys >> xt >> yt;
    _(int,n);
    _(vvi,circ,n,vi(3));
    circ.pb({xs,ys,0});
    circ.pb({xt,yt,0});
    vvd cost(n+2,vd(n+2));
    rep(i,n+2)
        rep(j,n+2)
            cost[i][j] = max(0.0,hypot(circ[i][0]-circ[j][0],circ[i][1]-circ[j][1])-circ[i][2]-circ[j][2]);
    vd dist(n+2,INF);
    vb visited(n+2);
    dist[n] = 0;
    priority_queue<pair<ld,int>> pq;
    pq.push({0,n});
    while(!pq.empty()){
        ld tmp;
        int u;
        tie(tmp,u) = pq.top();
        pq.pop();
        if(visited[u])
            continue;
        visited[u] = true;
        rep(i,n+2){
            if(!visited[i] && dist[i] > dist[u]+cost[u][i]){
                dist[i] = dist[u]+cost[u][i];
                pq.push({-dist[i],i});
            }
        }
    }
    print dist[n+1];
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);
        __();
}


Measured memory_bytes: 13808