結果
| 問題 |
No.168 ものさし
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2015-03-28 15:57:24 |
| 言語 | Ruby (3.4.1) |
| 結果 |
RE
|
| 実行時間 | - |
| コード長 | 3,270 bytes |
| コンパイル時間 | 203 ms |
| コンパイル使用メモリ | 7,552 KB |
| 実行使用メモリ | 23,296 KB |
| 最終ジャッジ日時 | 2024-06-29 01:28:37 |
| 合計ジャッジ時間 | 6,156 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 18 RE * 1 |
コンパイルメッセージ
Syntax OK
ソースコード
require 'set'
Problem168 = Struct.new(:points) do
def solve
@distance_cache = []
@grid = Grid.new(points)
w = isqrt(squared_distance_by_index(0, points.size - 1)) / 10
longest = ((w + 1) * 10) ** 2
shortest = -1
p 10 * (1..w + 1).bsearch {|d|
len = d * 10
sqlen = len ** 2
next true if longest <= sqlen
next false if sqlen < shortest
if minmax = reach(len, sqlen)
longest = minmax[1] if minmax[1] < longest
shortest = minmax[0] if shortest < minmax[0]
true
else
false
end
}
end
private
def isqrt(x)
(1..x).bsearch {|r| x <= r ** 2 }
end
def reach(len, sqlen)
goal = points.size - 1
stack = [0]
todo = Set.new(1..goal)
longest = -1
shortest = 1 / 0.0
while i = stack.pop
each_neighbor(i, len, sqlen, todo) do |j, distance|
longest = distance if longest < distance
shortest = distance if distance < shortest
return shortest, longest if j.equal?(goal)
stack << j
end
end
nil
end
def each_neighbor(i, len, sqlen, todo)
@grid.each_neighbor(i, len) do |j|
next unless todo.include?(j)
distance = squared_distance_by_index(i, j)
if distance <= sqlen
yield j, distance
todo.delete j
end
end
end
def squared_distance_by_index(ia, ib)
ia, ib = ib, ia if ib < ia
@distance_cache[ia * points.size + ib] ||= squared_distance(points[ia], points[ib])
end
def squared_distance(a, b)
ax, ay = a
bx, by = b
(ax - bx) ** 2 + (ay - by) ** 2
end
end
class Grid
def initialize(points)
@n = 5
@ax, @ay, @bx, @by = aabb(points)
@w = @bx - @ax
@h = @by - @ay
@cellw = @w / @n.to_r
@cellh = @h / @n.to_r
@points = points
@bucket_of = points.map {|pt| which_bucket pt }
@buckets = Array.new(@n * @n) { [] }
@bucket_of.each_with_index {|b, i| @buckets[b] << i }
end
def aabb(points)
ax = ay = bx = by = nil
points.each do |x, y|
ax = x if !ax || ax > x
ay = y if !ay || ay > y
bx = x if !bx || bx < x
by = y if !by || by < y
end
return ax, ay, bx, by
end
def which_bucket(point)
x, y = point
[(y - @ay) * @n / @h, @n - 1].min * @n + [(x - @ax) * @n / @w, @n - 1].min
end
def each_neighbor(ipoint, radius)
each_neighbor_bucket(ipoint, radius) do |bucket|
@buckets[bucket].each {|i| yield i }
end
end
def each_neighbor_bucket(ipoint, radius)
bw = [(radius / @cellw).ceil, @n - 1].min
bh = [(radius / @cellh).ceil, @n - 1].min
b = @bucket_of[ipoint]
bx = b % @n
yield b
(1..bw).each do |dx|
yield b - dx if bx >= dx
yield b + dx if bx + dx < @n
end
(1..bh).each do |dy|
if (bpy = b - dy * @n) >= 0
yield bpy
(1..bw).each do |dx|
yield bpy - dx if bx >= dx
yield bpy + dx if bx + dx < @n
end
end
if (bpy = b + dy * @n) < @n * @n
yield bpy
(1..bw).each do |dx|
yield bpy - dx if bx >= dx
yield bpy + dx if bx + dx < @n
end
end
end
end
end
Problem168.new((1..gets.to_i).map{gets.split.map(&:to_i)}).solve