#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef long double LD;
typedef pair<LD, int> PLDI;
typedef pair<LD, LD> PLDLD;

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define CLR(a) memset((a), 0 ,sizeof(a))
#define ALL(a) a.begin(),a.end()
const LL INF_LL = (1e15);
const int INF = (1e9);
const LL MOD = 1e9+7;
const double EPS = 1e-5;
const double PI=atan2(0,-1);

typedef LD Dist;

struct Edge;
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

struct Edge
{
    int to;
    Dist dist;
    Edge(int to_,Dist dist_):to(to_),dist(dist_)
    {}
    bool operator >(const Edge &ed)const
    {
        return dist > ed.dist;
    }
};

//Shortest cost from i to j.
vector<Dist> dijkstra(int i, const Graph &vertex, vector<int> &preVector)
{
    vector<int> pVector(vertex.size(), INF);
    vector<Dist> shortest(vertex.size(), INF_LL);
    priority_queue<Edge, vector<Edge>, greater<Edge> > que;

    que.push(Edge(i, 0));
    shortest[i]=0;

    Edge state(0,0), tmp(0,0), e(0,0);
    while(!que.empty())
    {
        state = que.top();
        que.pop();
        if(shortest[state.to] < state.dist) continue;
        for(Edge e : vertex[state.to])
        {
            if(shortest[e.to] > shortest[state.to] + e.dist)
            {
                shortest[e.to] = shortest[state.to] + e.dist;
                pVector[e.to] = state.to;
                tmp = Edge(e.to, shortest[e.to]);
                que.push(tmp);
            }
        }
    }
    preVector = pVector;
    return shortest;
}

vector<int> get_path(int i, int j, const vector<int> &preVector)
{
    vector<int> rev;
    rev.push_back(j);
    int p=j;
    while(p!=i)
    {
        p = preVector[p];
        rev.push_back(p);
        if(p==INF)
            return vector<int>();
    }
    reverse(rev.begin(),rev.end());
    return rev;
}

vector<Dist> dijkstra(int i, const Graph &vertex)
{
  vector<int> preVector(vertex.size());
  return dijkstra(i, vertex, preVector);
}
Dist dijkstra(int i,int j, const Graph &vertex)
{
  return dijkstra(i, vertex)[j];
}
Dist dijkstra(int i,int j, const Graph &vertex, vector<int> &path)
{
  vector<int> preVector(vertex.size());
  vector<Dist> shortest(dijkstra(i, vertex, preVector));
  path = get_path(i, j, preVector);
  return shortest[j];
}

struct Point
{
    int x, y;
    Point(int x_, int y_):x(x_),y(y_)
    {}

};
struct Circle
{
    Point p;
    int r;
    Circle(int x,int y,int r_):p(Point(x,y)), r(r_){}
    Circle():p(Point(0,0)), r(0){}
};
int main()
{
    int sx,sy,gx,gy,n;
    cin>>sx>>sy>>gx>>gy;
    Point s(sx,sy),g(gx,gy);
    cin>>n;
    
    Graph gr(n+2);
    vector<Circle> c(n);
    REP(i,n)
    {
        int x,y,r;
        cin>>x>>y>>r;
        c[i]=Circle(x,y,r);
    }
    c.push_back(Circle(s.x, s.y, 0));
    c.push_back(Circle(g.x, g.y, 0));
    REP(i,n+2)
    REP(j,n+2)
    {
        LD dis=sqrt((LD)pow(c[i].p.x-c[j].p.x,2)+pow(c[i].p.y-c[j].p.y, 2))-((LD)c[i].r+(LD)c[j].r);
        dis=max(dis,(LD)0.0);
        gr[i].push_back(Edge(j,dis));
        gr[j].push_back(Edge(i,dis));
        //cout<<i<<" "<<j<<" "<<dis<<endl;
    }

    cout<<setprecision(10)<<fixed<<dijkstra(n,n+1,gr)<<endl;
}

//abcb


Measured memory_bytes: 73324