結果
問題 | No.168 ものさし |
ユーザー | snipsnipsnip |
提出日時 | 2015-03-28 16:03:11 |
言語 | Ruby (3.4.1) |
結果 |
AC
|
実行時間 | 800 ms / 2,000 ms |
コード長 | 3,378 bytes |
コンパイル時間 | 68 ms |
コンパイル使用メモリ | 7,808 KB |
実行使用メモリ | 23,552 KB |
最終ジャッジ日時 | 2024-12-24 07:06:35 |
合計ジャッジ時間 | 6,188 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 367 ms
16,256 KB |
testcase_01 | AC | 101 ms
12,416 KB |
testcase_02 | AC | 100 ms
12,416 KB |
testcase_03 | AC | 103 ms
12,416 KB |
testcase_04 | AC | 101 ms
12,416 KB |
testcase_05 | AC | 106 ms
12,160 KB |
testcase_06 | AC | 101 ms
12,288 KB |
testcase_07 | AC | 106 ms
12,032 KB |
testcase_08 | AC | 103 ms
12,160 KB |
testcase_09 | AC | 106 ms
12,288 KB |
testcase_10 | AC | 119 ms
12,672 KB |
testcase_11 | AC | 243 ms
14,720 KB |
testcase_12 | AC | 276 ms
19,712 KB |
testcase_13 | AC | 359 ms
22,016 KB |
testcase_14 | AC | 156 ms
22,144 KB |
testcase_15 | AC | 104 ms
12,416 KB |
testcase_16 | AC | 108 ms
12,416 KB |
testcase_17 | AC | 116 ms
12,672 KB |
testcase_18 | AC | 116 ms
12,672 KB |
testcase_19 | AC | 312 ms
22,272 KB |
testcase_20 | AC | 211 ms
23,552 KB |
testcase_21 | AC | 800 ms
21,632 KB |
testcase_22 | AC | 563 ms
21,760 KB |
コンパイルメッセージ
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 by = @h == 0 ? @n - 1 : [(y - @ay) * @n / @h, @n - 1].min bx = @w == 0 ? @n - 1 : [(x - @ax) * @n / @w, @n - 1].min by * @n + bx 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 = @cellw == 0 ? @n - 1 : [(radius / @cellw).ceil, @n - 1].min bh = @cellh == 0 ? @n - 1 : [(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