AOJ(問題集)16
AIZU ONLINE JUDGE: Programming Challenge
0150 Twin Prime
N = 10007 sieve = [*0..N] 2.upto(Math.sqrt(N).to_i) do |i| next if sieve[i].zero? 2.upto(N / i) {|j| sieve[i * j] = 0} end sieve = sieve[2..-1].reject {|x| x.zero?} until (n = $<.gets.to_i).zero? idx = sieve.index {|i| i > n} - 1 i = 0 i += 1 until sieve[idx - i] - sieve[idx - i - 1] == 2 puts "#{sieve[idx - i - 1]} #{sieve[idx - i]}" end
N = 10000
ではダメなことになかなか気づかなかった。
0151 Grid
def count(line) line.chunk {|i| i.nonzero?}.select(&:first).map {|l| l.last.size}.max || 0 end until (n = $<.gets.to_i).zero? field = n.times.map {$<.gets.chomp.chars.map(&:to_i)} max_l = field.map {|l| count(l)}.max max_l = [field.transpose.map {|l| count(l)}.max, max_l].max l = n - 1 n.times do |i| line = (i + 1).times.map {|j| field[i - j][j]} tmp1 = count(line) line = (i + 1).times.map {|j| field[l - i + j][l - j]} tmp2 = count(line) line = (i + 1).times.map {|j| field[i - j][l - j]} tmp3 = count(line) line = (i + 1).times.map {|j| field[l - i + j][j]} tmp4 = count(line) max_l = [tmp1, tmp2, tmp3, tmp4, max_l].max end puts max_l end
0.50秒。素朴にやった。まあまあか。
0152 Bowling
until (m = $<.gets.to_i).zero? result = m.times.map do id, *score = $<.gets.split.map(&:to_i) th = 0 final_point = 10.times.map do |i| if i == 9 if score[th] == 10 or score[th, 2].sum == 10 score[th, 3].sum else score[th, 2].sum end elsif score[th] == 10 th += 1 10 + score[th, 2].sum elsif score[th, 2].sum == 10 th += 2 10 + score[th] else th += 2 score[th - 2, 2].sum end end.sum [id, final_point] end.sort {|a, b| (b[1] <=> a[1]).nonzero? || a[0] <=> b[0]} puts result.map {|a| a.join(" ")} end
複数キーのソートはここを参考にしました。
0153 Triangle and Circle
def perpendicular_foot(a, b, p) s = Rational((p - a).dot(b - a), (b - a).dot(b - a)) h = a + (b - a) * s [s, (h - p).norm] end def triangle_inside(a, b, c, p) s, t = Matrix.columns([b - a, c - a]).lup.solve(p - a).to_a s > 0 and t > 0 and 0 < s + t and s + t < 1 end until (p1 = $<.gets.split.map(&:to_i)) == [0, 0] p1 = Vector[*p1] p2 = Vector[*$<.gets.split.map(&:to_i)] p3 = Vector[*$<.gets.split.map(&:to_i)] c = Vector[*$<.gets.split.map(&:to_i)] r = $<.gets.to_i f1 = (p1 - c).norm f2 = (p2 - c).norm f3 = (p3 - c).norm g1 = (f1 <= r and f2 >= r) or (f1 >= r and f2 <= r) g2 = (f2 <= r and f3 >= r) or (f2 >= r and f3 <= r) g3 = (f3 <= r and f1 >= r) or (f3 >= r and f1 <= r) s, l = perpendicular_foot(p1, p2, c) h1 = (0 <= s and s <= 1) and (f1 >= r and f2 >= r) and l <= r e1 = l >= r and f1 > r and f2 > r s, l = perpendicular_foot(p2, p3, c) h2 = (0 <= s and s <= 1) and (f2 >= r and f3 >= r) and l <= r e2 = l >= r and f2 > r and f3 > r s, l = perpendicular_foot(p3, p1, c) h3 = (0 <= s and s <= 1) and (f3 >= r and f1 >= r) and l <= r e3 = l >= r and f3 > r and f1 > r e0 = triangle_inside(p1, p2, p3, c) result = if e0 and e1 and e2 and e3 "a" elsif f1 <= r and f2 <= r and f3 <= r "b" elsif g1 or g2 or g3 or h1 or h2 or h3 "c" else "d" end puts result end
Wrong Answer.
require 'matrix' def perpendicular_foot(a, b, p) s = Rational((p - a).dot(b - a), (b - a).dot(b - a)) h = a + (b - a) * s (h - p).norm end def triangle_inside(a, b, c, p) s, t = Matrix.columns([b - a, c - a]).lup.solve(p - a).to_a s > 0 and t > 0 and 0 < s + t and s + t < 1 end until (p1 = $<.gets.split.map(&:to_i)) == [0, 0] p1 = Vector[*p1] p2 = Vector[*$<.gets.split.map(&:to_i)] p3 = Vector[*$<.gets.split.map(&:to_i)] c = Vector[*$<.gets.split.map(&:to_i)] r = $<.gets.to_i f1 = (p1 - c).norm f2 = (p2 - c).norm f3 = (p3 - c).norm l = perpendicular_foot(p1, p2, c) h1 = l > r e1 = l >= r and f1 > r and f2 > r l = perpendicular_foot(p2, p3, c) h2 = l > r e2 = l >= r and f2 > r and f3 > r l = perpendicular_foot(p3, p1, c) h3 = l > r e3 = l >= r and f3 > r and f1 > r e0 = triangle_inside(p1, p2, p3, c) result = if e0 and e1 and e2 and e3 "a" elsif f1 <= r and f2 <= r and f3 <= r "b" elsif f1 > r and f2 > r and f3 > r and h1 and h2 and h3 "d" else "c" end puts result end
Wrong Answer.
require 'matrix' def perpendicular_foot(a, b, p) s = Rational((p - a).dot(b - a), (b - a).dot(b - a)) h = a + (b - a) * s (h - p).norm end def triangle_inside(a, b, c, p) s, t = Matrix.columns([b - a, c - a]).lup.solve(p - a).to_a s > 0 and t > 0 and 0 < s + t and s + t < 1 end until (p1 = $<.gets.split.map(&:to_i)) == [0, 0] p1 = Vector[*p1] p2 = Vector[*$<.gets.split.map(&:to_i)] p3 = Vector[*$<.gets.split.map(&:to_i)] c = Vector[*$<.gets.split.map(&:to_i)] r = $<.gets.to_i f1 = (p1 - c).norm f2 = (p2 - c).norm f3 = (p3 - c).norm h1 = perpendicular_foot(p1, p2, c) h2 = perpendicular_foot(p2, p3, c) h3 = perpendicular_foot(p3, p1, c) e0 = triangle_inside(p1, p2, p3, c) result = if h1 >= r and h2 >= r and h3 >= r and e0 "a" elsif h1 > r and h2 > r and h3 > r and !e0 "d" elsif f1 <= r and f2 <= r and f3 <= r "b" else "c" end puts result end
Wrong Answer.
require 'matrix' def perpendicular_foot(a, b, p) s = Rational((p - a).dot(b - a), (b - a).dot(b - a)) h = a + (b - a) * s (h - p).dot(h - p) end def triangle_inside(a, b, c, p) s, t = Matrix.columns([b - a, c - a]).lup.solve(p - a).to_a s > 0 and t > 0 and 0 < s + t and s + t < 1 end until (p1 = $<.gets.split.map(&:to_i)) == [0, 0] p1 = Vector[*p1] p2 = Vector[*$<.gets.split.map(&:to_i)] p3 = Vector[*$<.gets.split.map(&:to_i)] c = Vector[*$<.gets.split.map(&:to_i)] r = $<.gets.to_i ** 2 f1 = (p1 - c).dot(p1 - c) f2 = (p2 - c).dot(p2 - c) f3 = (p3 - c).dot(p3 - c) h1 = perpendicular_foot(p1, p2, c) h2 = perpendicular_foot(p2, p3, c) h3 = perpendicular_foot(p3, p1, c) e0 = triangle_inside(p1, p2, p3, c) result = if f1 <= r and f2 <= r and f3 <= r "b" elsif f1 > r and f2 > r and f3 > r min_h = [h1, h2, h3].min if e0 and min_h >= r "a" elsif !e0 and min_h > r "d" else "c" end else "c" end puts result end
Wrong Answer.
0154 Sum of Cards
until (m = $<.gets.to_i).zero? cards = m.times.map {$<.gets.split.map(&:to_i)} ln = cards.map {|a, b| a * b}.sum table = [0] cards.each do |a, b| table = table.flat_map do |num| (b + 1).times.map {|i| num + a * i} end end $<.gets.to_i.times do puts table.count($<.gets.to_i) end end
20.9秒もかかったのに accept された。
他の人の回答を見てみた。
until (m = $<.gets.to_i).zero? cards = m.times.map {$<.gets.split.map(&:to_i)} memo = Array.new(cards.size + 1) {[]} $<.gets.to_i.times do count = ->(i, left) { return memo[i][left] if memo[i][left] if i >= cards.length co = left.zero? ? 1 : 0 else co = 0 a, b = cards[i] (b + 1).times do |j| nxt = left - a * j break if nxt < 0 co += count.(i + 1, nxt) end end memo[i][left] = co } puts count.(0, $<.gets.to_i) end end
0.07秒…。何でこれに気づかない…。
0155 Spider Jin
until (n = $<.gets.to_i).zero? buildings = n.times.map {$<.gets.split.map(&:to_i)} sg = $<.gets.to_i.times.map {$<.gets.split.map(&:to_i)} table = Hash.new {|h, k| h[k] = {}} buildings.combination(2) do |a, b| ida, xa, ya = a idb, xb, yb = b dist = (xa - xb) ** 2 + (ya - yb) ** 2 next if dist > 50 ** 2 table[ida][idb] = Math.sqrt(dist) table[idb][ida] = Math.sqrt(dist) end h = table.map {|k, v| [k, v.keys]}.to_h sg.each do |s, g| shortest = Hash.new(Float::INFINITY) pred = {} done = h.keys.map {|k| [k, false]}.to_h shortest[s] = 0 loop do u = nil h.each_key do |node| next if done[node] u = node if !u or shortest[node] < shortest[u] end break unless u done[u] = true h[u].each do |v| if (a = shortest[u] + table[u][v]) < shortest[v] shortest[v] = a pred[v] = u end end end result = if pred[g] order = [] while g order.unshift(g) g = pred[g] end order.join(" ") else "NA" end puts result end end
ダイクストラ法。
0156
until (a = io.gets.split.map(&:to_i)) == [0, 0] n, m = a field = m.times.map {io.gets.chomp.chars} i = field.flatten.index("&") numbering = ->(x, y, num) { type = field[y][x] queue = [[x, y]] while (a = queue.shift) x0, y0 = a field[y0][x0] = num [[1, 0], [0, -1], [-1, 0], [0, 1]].each do |dx, dy| x1 = x0 + dx y1 = y0 + dy return num if x1 < 0 or x1 >= n or y1 < 0 or y1 >= m next if field[y1][x1] != type next if ![".", "#", "&"].include?(field[y1][x1]) queue << [x1, y1] end end false } catch :jump do x, y = i % n, i / n [[1, 0], [0, -1], [-1, 0], [0, 1]].each do |dx, dy| x1 = x + dx y1 = y + dy if x1 < 0 or x1 >= n or y1 < 0 or y1 >= m puts 0 throw :jump else num = (field[y1][x1] == "#") ? 0 : 1 num = numbering.(x1, y1, num) if num puts 0 throw :jump end end end puts -1 end puts field.map(&:join) end
考え中。
0157 Russian Dolls
until (n = $<.gets.to_i).zero? ichiro = n.times.map {$<.gets.split.map(&:to_i)} .sort {|a, b| (b[0] <=> a[0]).nonzero? || b[1] <=> a[1]} m = $<.gets.to_i jiro = m.times.map {$<.gets.split.map(&:to_i)} .sort {|a, b| (b[0] <=> a[0]).nonzero? || b[1] <=> a[1]} memo = {} try = ->(h, r, ichi, ji) { key = "#{h},#{r},#{ichi},#{ji}" return memo[key] if memo[key] return 0 if ichi >= n and ji >= m co1 = co2 = 0 if ichiro[ichi] if h > ichiro[ichi][0] and r > ichiro[ichi][1] co1 = 1 + try.(ichiro[ichi][0], ichiro[ichi][1], ichi + 1, ji) else co1 = try.(h, r, ichi + 1, ji) end end if jiro[ji] if h > jiro[ji][0] and r > jiro[ji][1] co2 = 1 + try.(jiro[ji][0], jiro[ji][1], ichi, ji + 1) else co2 = try.(h, r, ichi, ji + 1) end end memo[key] = (co1 > co2) ? co1 : co2 } puts try.(Float::INFINITY, Float::INFINITY, 0, 0) end
これで 0.14秒。自力で考えたオレはえらいが、これは DAG(閉路なし有向グラフ)の最長経路問題なのだった。
なので、動的計画法で解くのがふつうらしい。こんな感じ。
until (n = $<.gets.to_i).zero? dolls = n.times.map {$<.gets.split.map(&:to_i)} m = $<.gets.to_i dolls += m.times.map {$<.gets.split.map(&:to_i)} dolls.sort! {|a, b| (b[0] <=> a[0]).nonzero? || b[1] <=> a[1]} longest = Array.new(n + m, 0) (0..n + m - 2).each do |i| (i + 1...n + m).each do |j| if dolls[i][0] > dolls[j][0] and dolls[i][1] > dolls[j][1] if (a = longest[i] + 1) > longest[j] longest[j] = a end end end end puts longest.last + 1 end
これで 0.06秒。
0158 Collatz's Problem
@memo = {} def try(n) return @memo[n] if @memo[n] return 0 if n == 1 co = if n.even? try(n / 2) else try(n * 3 + 1) end @memo[n] = co + 1 end until (n = $<.gets.to_i).zero? puts try(n) end
0159 The Best Body
until (n = $<.gets.to_i).zero? min_dif = Float::INFINITY persons = [] n.times.map {$<.gets.split.map(&:to_i)}.each do |p, h, w| h = Rational(h, 100) dif = (Rational(w, h * h) - 22).abs if dif < min_dif persons = [p] min_dif = dif elsif dif == min_dif persons << p end end puts persons.sort.first end