#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
#![allow(unused_mut)]
#![allow(unused_variables)]
#![allow(dead_code)]

use itertools::Itertools;
use proconio::input;
use proconio::marker::{Chars, Usize1};

#[allow(unused_macros)]
#[cfg(debug_assertions)]
macro_rules! mydbg {
    //($arg:expr) => (dbg!($arg))
    //($arg:expr) => (println!("{:?}",$arg));
      ($($a:expr),*) => {
          eprintln!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
      }
}
#[cfg(not(debug_assertions))]
macro_rules! mydbg {
    ($($arg:expr),*) => {};
}

macro_rules! echo {
    ($($a:expr),*) => {
          $(println!("{}",$a))*
      }
}

use std::cmp::*;
use std::collections::*;
use std::ops::{Add, Div, Mul, Sub};

#[allow(dead_code)]
static INF_I64: i64 = 92233720368547758;
#[allow(dead_code)]
static INF_I32: i32 = 21474836;
#[allow(dead_code)]
static INF_USIZE: usize = 18446744073709551;
#[allow(dead_code)]
static M_O_D: usize = 1000000007;
#[allow(dead_code)]
static PAI: f64 = 3.1415926535897932;

trait IteratorExt: Iterator {
    fn toVec(self) -> Vec<Self::Item>;
}

impl<T: Iterator> IteratorExt for T {
    fn toVec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

trait CharExt {
    fn toNum(&self) -> usize;
    fn toAlphabetIndex(&self) -> usize;
    fn toNumIndex(&self) -> usize;
}
impl CharExt for char {
    fn toNum(&self) -> usize {
        return *self as usize;
    }
    fn toAlphabetIndex(&self) -> usize {
        return self.toNum() - 'a' as usize;
    }
    fn toNumIndex(&self) -> usize {
        return self.toNum() - '0' as usize;
    }
}

trait VectorExt {
    fn joinToString(&self, s: &str) -> String;
}
impl<T: ToString> VectorExt for Vec<T> {
    fn joinToString(&self, s: &str) -> String {
        return self
            .iter()
            .map(|x| x.to_string())
            .collect::<Vec<_>>()
            .join(s);
    }
}

trait StringExt {
    fn get_reverse(&self) -> String;
}
impl StringExt for String {
    fn get_reverse(&self) -> String {
        self.chars().rev().collect::<String>()
    }
}

trait UsizeExt {
    fn pow(&self, n: usize) -> usize;
}
impl UsizeExt for usize {
    fn pow(&self, n: usize) -> usize {
        return ((*self as u64).pow(n as u32)) as usize;
    }
}
use ordered_float::OrderedFloat;

pub struct Dikstra {
    dist: Vec<f64>,
    start: usize,
}
impl Dikstra {
    pub fn new(g: &Vec<Vec<(f64, usize)>>, start: usize) -> Self {
        let mut d = Dikstra {
            dist: vec![INF_I64 as f64; g.len()],
            start: start,
        };
        d.calc(g);
        return d;
    }
    fn calc(&mut self, g: &Vec<Vec<(f64, usize)>>) {
        let mut used = vec![false; g.len()];
        let mut kouho = std::collections::BinaryHeap::new();
        kouho.push((OrderedFloat(0_f64), self.start));
        while !kouho.is_empty() {
            let (_, k) = kouho.pop().unwrap();
            used[self.start] = true;
            self.dist[self.start] = 0_f64;
            for i in 0..g[k].len() {
                let (d, p) = g[k][i];
                if used[p] {
                    continue;
                }
                if self.dist[p] > self.dist[k] + d as f64 {
                    self.dist[p] = self.dist[k] + d as f64;
                    kouho.push((OrderedFloat(self.dist[p] * -1_f64), p));
                }
            }
        }
    }
    pub fn dist_to(&mut self, x: usize) -> f64 {
        return self.dist[x];
    }
}

fn main() {
    input! {
       sx:f64,
       sy:f64,
       gx:f64,
       gy:f64,
       N:usize,
       mut p:[(f64,f64,f64);N],
    }

    p.push((sx, sy, 0.0));
    let start = p.len() - 1;
    p.push((gx, gy, 0.0));
    let goal = p.len() - 1;

    let mut ans: usize = 0;
    let mut map = vec![vec![]; p.len()];
    for i in 0..p.len() {
        let (x, y, r) = p[i];
        for j in i + 1..p.len() {
            let (x2, y2, r2) = p[j];
            let s = x2 - x;
            let t = y2 - y;
            let dist = (s * s + t * t).sqrt();
            let mut cost = dist - r - r2;
            if cost < 0.0 {
                cost = 0.0;
            }
            map[i].push((cost, j));
            map[j].push((cost, i));
        }
    }

    let mut dik = Dikstra::new(&map, start);
    let ans = dik.dist_to(goal);

    echo!(ans);
}


Measured memory_bytes: 22564