#include <bits/stdc++.h>

#define oo DBL_MAX

using namespace std;

class sigment{
    public:
        double x1,y1,x2,y2 ;

        sigment(double x1,double y1,double x2,double y2){
            this-> x1 = x1 ;
            this-> y1 = y1 ;
            this-> x2 = x2 ;
            this-> y2 = y2 ;
        }

        double displacment(){
            return sqrt(pow(y2 - y1 , 2) + pow(x2 - x1 , 2)) ;
        }
};

class circle{
public:
    int index;
    double  x , y , radius ;

    circle(double x , double y , double radius , int index){
        this->x = x ;
        this->y = y ;
        this->radius = radius ;
        this->index = index ;
    }

    double distance(circle c){
        sigment sig(this->x,this->y,c.x,c.y) ;
        double displacment = sig.displacment() ;
        if(displacment > this->radius + c.radius)
            return displacment - (this->radius + c.radius) ;
        return 0 ;
    }
};

class edge{
public:
    int from , to , index ;
    double weight ;

    edge(int from , int to , double weight , int index){
        this->from = from ;
        this->to = to ;
        this->index = index ;
        this->weight = weight ;
    }
};

class graph{
public:
    vector<vector<edge>> lis ;

    graph(int vertices){
        lis.resize(vertices) ;
    }

    void add_edge(int from , int to , double weight, int index){
        lis[from].push_back(edge(from,to,weight,index)) ;
    }

    void print(){
        for(int i = 0 ; i < (int)lis.size() ; i++){
            for(int j = 0 ; j < (int)lis[i].size() ; j++){
                cout << "from : " << i+1 << " to : " << lis[i][j].to << " weight : " << lis[i][j].weight << endl ;
            }
        }
    }
};

struct EdgeCompare {
    bool operator() (edge& e1 , edge& e2){
        return e1.weight > e2.weight ;
    }
};


void print_dis(vector<long long> dis){
    for(int i = 1 ; i < (int)dis.size() ; i++){
        cout << "to : " << i << " dis : " << dis[i] << endl ;
    }
}


void read_edge(int index , graph& lis){
    int from , to ;
    cin >> from >> to;
    lis.add_edge(from,to,-1,index) ;
    lis.add_edge(to,from,-1,index) ;
}

double shortest_path(int from , graph gr, int n_vertices){

    vector<double> dis(n_vertices , oo) ;
    vector<bool> vis(n_vertices , false) ;
    vector<int> parent(n_vertices , -1) ;
    vector<int> parent_edge(n_vertices , -1) ;
    priority_queue<edge , vector<edge> , EdgeCompare> edges ;

    edges.push(edge(from,from,0,-1)) ;
    dis[from] = 0 ;

    while(!edges.empty()){

        edge curr = edges.top() ;
        edges.pop() ;

        if(vis[curr.to])
            continue ;

        vis[curr.to] = true ;

        for(edge e : gr.lis[curr.to]){
            double w = dis[curr.to] + e.weight ;
            if(dis[e.to] > w){
                dis[e.to] = w ;
                edges.push(edge(curr.to,e.to,dis[e.to],-1)) ;
                parent[e.to] = curr.to ;
                parent_edge[e.to] = e.index ;
            }
        }

    }


    return dis.back() ;
}


void build_graph(graph& lis , vector<circle> circles){

    for(int i = 0 ; i < (int)circles.size() ; i++){
        for(int j = 0 ; j < (int)circles.size() ; j++){
            if(i != j){
                lis.add_edge(i,j,circles[i].distance(circles[j]),-1) ;
            }
        }
    }

}

int main()
{
//    print_dis(dis) ;

    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

 //   freopen("in.txt","r",stdin) ;

    vector<circle> circles ;

    double bx , by , ex , ey ;

    cin >> bx >> by >> ex >> ey ;

    int v ; cin >> v ;



    circles.push_back(circle(bx,by,0,0));
    for(int i = 0 ; i < v ; i++){
        double cx , cy , cr ;
        cin >> cx >> cy >> cr ;
        circles.push_back(circle(cx,cy,cr,i+1)) ;
    }
    circles.push_back(circle(ex,ey,0,circles.size())) ;


    v += 2 ;
    graph lis(v) ;
    build_graph(lis,circles) ;

    cout.precision(19);
    cout << shortest_path(0,lis,v) ;

    return 0;
}


Measured memory_bytes: 57240