require 'matrix'

include Math



class Heap

	require 'forwardable'

	extend Forwardable



	def initialize

		@array = []

		@index = {}

	end



	def add(obj, key)

		@array << [obj, key]

		@index[obj] = @array.size - 1

		lift_up(@array.size - 1)

	end



	def swap(i, j)

		u = @array[i]

		v = @array[j]

		@index[u[0]], @index[v[0]] = j, i

		@array[i], @array[j] = v, u

	end



	def lift_up(i)

		return if i == 0

		j = (i - 1) / 2

		if (@array[i][1] <=> @array[j][1]) < 0

			swap(i, j)

			lift_up(j)

		end

	end



	def del_min

		raise "heap is empty!" if empty?

		min = @array[0]

		if size > 1

			swap(0, @array.size-1)

			@array.pop

			lift_down(0)

		else

			@array.pop

		end

		@index.delete(min[0])

		min

	end



	def inc_key(obj, diff)

		i = @index[obj]

		@array[i][1] += diff

		lift_down(i)

	end



	def dec_key(obj, diff)

		i = @index[obj]

		@array[i][1] -= diff

		lift_up(i)

	end



	def update_key(obj, new_key)

		i = @index[obj]

		return unless i

		return if (new_key <=> @array[i][1]) >= 0

		@array[i][1] = new_key

		lift_up(i)

	end



	def min_obj

		@array[0][0]

	end



	def min_key

		@array[0][1]

	end



	def lift_down(i)

		j = 2 * i + 1

		k = j + 1

		if k >= size

			return if j >= size

			if (@array[i][1] <=> @array[j][1]) > 0

				swap(i, j)

				lift_down(j)

			end

		else

			l = ((@array[j][1] <=> @array[k][1]) < 0 ? j : k)

			if (@array[i][1] <=> @array[l][1]) > 0

				swap(i, l)

				lift_down(l)

			end

		end

	end



	def_delegators :@array, :empty?, :size

end



module Graphical

	require 'set'



	def get_path_by_bfs(s, t)

		prev_node = {}

		reached = Set[s]

		queue = [s]

		while !queue.empty? 

			u = queue.shift

			each_out_connection_of(u){|v, _|

				next if reached.include?(v)	

				reached << v

				queue << v

				prev_node[v] = u



				if v == t

					path = [v]

					while v = prev_node[v]

						path.unshift v

					end

					return path

				end

			}

		end	

		return nil

	end



	def get_path_by_dfs(s, t, reached = Set.new)

		reached << s

		return [s] if s == t

		each_out_connection_of(s){|v|

			next if reached.include?(v)

			path = get_path_by_dfs(v, t, reached) 

			return [s] + path if path

		}

		nil

	end



	def reachable_from(s, max_depth = nil)

		reached = Set[s]

		queue = [s]

		depth = 0

		loop {

			break if max_depth && depth >= max_depth

			next_queue = []

			until queue.empty?

				u = queue.shift

				each_out_connection_of(u){|v, _|

					next if reached.include?(v)

					reached << v

					next_queue << v

				}

			end

			break if next_queue.empty?

			queue = next_queue

			depth += 1

		}

		return reached

	end



	def bfs(start)

		raise "start must be Enumerable" if !start.kind_of?(Enumerable)

		reached = Set[*start.to_a]

		queue = []

		start.each{|s| queue << s}

		dist = {}

		loop.with_index {|_, depth|

			next_queue = []

			until queue.empty?

				u = queue.shift

				return depth if block_given? && yield(u, depth)

				dist[u] = depth

				each_out_connection_of(u){|v, _|

					next if reached.include?(v)

					reached << v

					next_queue << v

				}

			end

			break if next_queue.empty?

			queue = next_queue

		}

		block_given? ? nil : dist

	end



	def dijkstra(start)

		raise "start must be Enumerable" if !start.kind_of?(Enumerable)

		h = Heap.new

		reached = Set[*start.to_a]

		start.each{|s| h.add(s, 0)}



		dist = {}

		until h.empty?

			u, key = h.del_min

			return key if block_given? && yield(u, key)

			dist[u] = key

			each_out_connection_of(u){|v, l|

				d = dist[u] + l

				if reached.include?(v)

					h.update_key(v, d)

				else

					h.add(v, d)

					reached << v

				end

			}

		end

		block_given? ? nil : dist

	end



	def bidir_dijkstra(s, t)

		f_dist = {}

		b_dist = {}



		f_heap = Heap.new

		b_heap = Heap.new



		f_heap.add(s, 0)

		b_heap.add(t, 0)



		f_reached = Set[s]

		b_reached = Set[t]



		f_current_dist = b_current_dist = 0

		best = Float::INFINITY



		loop {

			if !f_heap.empty?

				u, key = f_heap.del_min

				f_dist[u] = key

				f_current_dist = key

				each_out_connection_of(u){|v, l|

					d = f_dist[u] + l

					if b_dist[v]

						path_len = d + b_dist[v]

						best = path_len if path_len < best

					end

					if f_reached.include?(v)

						f_heap.update_key(v, d)

					else

						f_heap.add(v, d)

						f_reached << v

					end

				}

			end



			if !b_heap.empty?

				u, key = b_heap.del_min

				b_dist[u] = key

				b_current_dist = key

				each_in_connection_of(u){|v, l|

					d = b_dist[u] + l

					if f_dist[v]

						path_len = d + f_dist[v]

						best = path_len if path_len < best

					end

					if b_reached.include?(v)

						b_heap.update_key(v, d)

					else

						b_heap.add(v, d)

						b_reached << v

					end

				}

			end



			return best if f_current_dist + b_current_dist >= best

			return nil if f_heap.empty? && b_heap.empty?

		}

	end



	def a_star(start)

		raise "a_star need termination condition" unless block_given?

		h = Heap.new

		reached = Set[start]

		h.add(start, [a_star_heuristic(start), 0])



		dist = {}

		until h.empty?

			u, (e, d) = h.del_min

			return d if yield(u, dist)

			dist[u] = d

			each_out_connection_of(u){|v, l|

				d = dist[u] + l

				e = d + a_star_heuristic(v)

				if reached.include?(v)

					h.update_key(v, [e, d])

				else

					h.add(v, [e, d])

					reached << v

				end

			}

		end

		block_given? ? nil : dist

	end



	#make_variations :bidir_dijkstra



	def prim(start)

		h = Heap.new

		h.add(start, 0)

		reached = Set[start]

		tree_len = 0



		until h.empty?

			u, key = h.del_min

			tree_len += key



			each_out_connection_of(u){|v, d|

				if reached.include?(v)

					h.update_key(v, d)

				else

					h.add(v, d)

					reached << v

				end

			}

		end

		tree_len

	end



	def each_layer_from(start)

		raise "start must be Enumerable" if !start.kind_of?(Enumerable)

		return enum_for(__method__, start) unless block_given?

		reached = Set[*start]

		current_layer = start



		loop {

			yield current_layer

			next_layer = []

			current_layer.each{|u|

				each_out_connection_of(u){|v|

					next if reached.include?(v)

					reached << v

					next_layer << v

				}

			}	



			return if next_layer.empty?

			current_layer = next_layer

		}

	end

end



class Graph

	include Graphical



	def initialize(*options)

		@options = Set[*options]

	end



	def add_node(property = {})

		Node.new(property)

	end



	def add_edge(u, v, property = {})

		e = Edge.new(u, v, property)

		u.add_edge(e)

		v.add_edge(e)

		e

	end

	

	def del_edge(e)

		u, v = e.opposite.keys

		u.del_edge(e)

		v.del_edge(e)

		e

	end



	class Node

		def initialize(property)

			@property = property

			@edges = Set.new

		end



		def add_edge(e)

			@edges << e

		end



		def del_edge(e)

			@edges.delete(e)

		end



		def to_s

			@property[:name] || super

		end



		def each_edge

			@edges.each{|e| 

				yield e

			}

		end



		attr_reader :property

	end



	class Edge

		def initialize(u, v, property)

			@opposite = {u => v, v => u}

			@property = property

		end

		attr_reader :opposite, :property



		def to_s

			@property[:name] || super

		end



		def length

			@property[:length] || 1

		end

	end



	def each_out_connection_of(u)

		u.each_edge{|e|

			yield(e.opposite[u], e.length)

		}

	end



	alias :each_in_connection_of :each_out_connection_of

end



def rotation_matrix(radian)

	Matrix[

		[Math.cos(radian), -Math.sin(radian)],

		[Math.sin(radian),  Math.cos(radian)]

	]

end



class Line

	def initialize(*args)

		@x1, @y1, @x2, @y2 = args

		@a = @y2 - @y1

		@b = @x1 - @x2

		@c = @a * @x1 + @b * @y1

	end	



	def distance(x, y)

		v1 = Vector[@x2 - @x1, @y2 - @y1]

		v2 = Vector[x - @x1, y - @y1]

		v3 = Vector[x - @x2, y - @y2]

		x = v1.inner_product(v2) / v1.r



		d = sqrt([v2.r ** 2 - x ** 2, 0].max)

		a = v2.r

		b = v3.r

		c = v1.r

		if a * a + b * b - c * c < 0

			d

		else

			a < b ? a : b

		end

	end



	def parallel?(l)

		@a * l.b - @b * l.a == 0

	end



	def cross?(l)

		(@a * l.x1 + @b * l.y1 + @c) * (@a * l.x2 + @b * l.y2 + @c) <= 0 and

		(l.a * @x1 + l.b * @y1 + l.c) * (l.a * @x2 + l.b * @y2 + l.c) <= 0

	end



	def cross_point_vec(l)

		m = Matrix[

			[@a, @b],

			[l.a, l.b]

			]

		v = Vector[@c, l.c]

		(m.inv * v)

	end

	attr_reader :a, :b, :c, :x1, :y1, :x2, :y2

end



class Star

	def initialize(*args)

		@x, @y, @a, @r = args

		c = Vector[@x, @y]

		v = Vector[0, @r]

		v = rotation_matrix(@a * PI / 180) * v

		@points = (1..5).map do

			(c + v).tap { v = rotation_matrix(144 * PI / 180) * v }

		end

		@points

		@lines = (@points + [@points[0]]).each_cons(2).map do |p1, p2|

			Line.new(*p1, *p2)

		end

	end

	

	def distance(star)

		@lines.each do |l1|

			star.lines.each do |l2|

				return 0 if l1.cross?(l2)

			end

		end	



		ds = []

		@points.each do |p|

			star.lines.each do |l|

				ds << l.distance(*p.to_a)

			end

		end	

		star.points.each do |p|

			@lines.each do |l|

				ds << l.distance(*p.to_a)

			end

		end	

		ds.min

	end



	attr_reader :lines, :points
end

loop do

	n, m, l = gets.split.map(&:to_i)

	break if n == 0

	stars = (0..n-1).map { Star.new(*gets.split.map(&:to_i)) }

	g = Graph.new

	nodes = (0..n-1).map { g.add_node }

	(0..n-1).to_a.combination(2) do |i, j|

		g.add_edge(nodes[i], nodes[j], {:length => stars[i].distance(stars[j])})

	end

	p g.dijkstra([nodes[m-1]])[nodes[l-1]]

end