#include <bits/stdc++.h>
using namespace std;

#define rep(i, N) for (int i = 0; i < N; i++)

using ll = long long int;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

// Graph.h start--------------------------------------------
#pragma once

#include <vector>

using Weight = double;

struct Vertex;
using Vertices = std::vector<Vertex>;
struct Edge;
using Edges = std::vector<Edge>;

struct Vertex
{
	const int id;
	Edges edges;
	std::vector<int> ids_dst;

	Vertex(const int id);
	Vertex(const Vertex &rhs);
	void add_edge(const Edge &e);
};

struct Edge
{
	const int id_src, id_dst;
	Weight weight;

	Edge(const int id_src, const int id_dst, const Weight weight);
	Edge(const Edge &rhs);
};

struct Graph
{
	Vertices vertices;
	Edges edges;

	Graph(const int nvertices);
	Graph();
	Graph(const Graph &rhs);
	void add_edge(const Edge &edge);
	void add_edge(const int id_src, const int id_dst, const Weight w);
};

//----------------------------------------------------------

using namespace std;

Vertex::Vertex(const int id) : id(id) {}
Vertex::Vertex(const Vertex &rhs) : id(rhs.id), edges(rhs.edges), ids_dst(rhs.ids_dst) {}
void Vertex::add_edge(const Edge &e)
{
	edges.push_back(e);
	ids_dst.push_back(e.id_dst);
}

Edge::Edge(const int id_src, const int id_dst, const Weight weight) : id_src(id_src), id_dst(id_dst), weight(weight) {}
Edge::Edge(const Edge &rhs) : id_src(rhs.id_src), id_dst(rhs.id_dst), weight(rhs.weight) {}
bool operator<(const Edge &e1, const Edge &e2)
{
	return e1.weight != e2.weight ? e1.weight > e2.weight : // !!INVERSE!!
			   e1.id_src != e2.id_src ? e1.id_src < e2.id_src : e1.id_dst < e2.id_dst;
}

Graph::Graph(const int nvertices)
{
	for (int id = 0; id < nvertices; id++)
		vertices.push_back(Vertex(id));
}
Graph::Graph() : Graph(0) {}
Graph::Graph(const Graph &rhs) : vertices(rhs.vertices), edges(rhs.edges) {}
void Graph::add_edge(const Edge &edge)
{
	edges.push_back(edge);
	vertices[edge.id_src].add_edge(edge);
}
void Graph::add_edge(const int id_src, const int id_dst, const Weight w = 1)
{
	add_edge(Edge(id_src, id_dst, w));
}

// Graph.h end----------------------------------------------

using Pwi = pair<Weight, int>;
vector<Weight> dijkstra(const Graph &g, const int id_start, const Weight INF)
{
	const int n = (int)g.vertices.size();
	vector<Weight> d(n, INF);
	d[id_start] = 0;
	vector<bool> is_used(n, false);
	priority_queue<Pwi, vector<Pwi>, greater<Pwi>> que;

	que.push(Pwi(0, id_start));
	while (!que.empty())
	{
		const int id_src = que.top().second; // que.top().first >= d[id_src]
		que.pop();

		if (is_used[id_src])
			continue;
		is_used[id_src] = true;

		for (const Edge &edge : g.vertices[id_src].edges)
		{
			const int id_dst = edge.id_dst;
			if (d[id_dst] > d[id_src] + edge.weight)
			{
				d[id_dst] = d[id_src] + edge.weight;
				que.push(Pwi(d[id_dst], id_dst));
			}
		}
	}

	return d;
}

double dist(double x0, double y0, double x1, double y1)
{
    double dx = x0 - x1;
    double dy = y0 - y1;
    return sqrt(dx * dx + dy * dy);
}

int main()
{
    const double inf = pow(10, 10);

    int xs, ys, xt, yt;
    cin >> xs >> ys >> xt >> yt;
    int N;
    cin >> N;
    vector<int> x(N + 2), y(N + 2), r(N + 2, 0);
    rep(i, N) cin >> x[i] >> y[i] >> r[i];
    int s = N, t = N + 1;
    x[s] = xs;
    y[s] = ys;
    x[t] = xt;
    y[t] = yt;

    // make graph
    Graph g(N + 2);
    rep(i, N + 2) for (int j = i + 1; j < N + 2; j++)
    {
        double w = max(0.0, dist(x[i], y[i], x[j], y[j]) - r[i] - r[j]);
        g.add_edge(i, j, w);
        g.add_edge(j, i, w);
    }

    // output d_min
    double d_min = dijkstra(g, s, inf)[t];

    cout << fixed << setprecision(9) << d_min << endl;
}

Measured memory_bytes: 45284