AOJ(問題集)24
0230 Ninja Climbing
WA。いいと思うんだけれどなあ。
KABE = 0 HASHIGO = 1 SUBERU = 2 loop do n = gets.to_i break if n.zero? bils = Array.new(2) { gets.split.map(&:to_i) } bil_ck_init = Array.new(n) #trueだと到達済み #aがいま居るビル、bが反対側のビル(0 or 1)。nowは階数、coはジャンプした回数 try = ->(a, b, now, a_bil_ck, b_bil_ck, co) { return nil if a_bil_ck[now] a_bil_ck[now] = true return co if now >= n - 1 && bils[a][now] != SUBERU jump = ->{ f1 = try.(b, a, now + 2, b_bil_ck, a_bil_ck, co + 1) if now + 2 < n f2 = try.(b, a, now + 1, b_bil_ck, a_bil_ck, co + 1) if now + 1 < n f3 = try.(b, a, now, b_bil_ck, a_bil_ck, co + 1) if f1 || f2 || f3 [f1, f2, f3].compact.min else nil end } case bils[a][now] when KABE jump.() when HASHIGO if bils[a][now + 1] != HASHIGO jump.() else try.(a, b, now + 1, a_bil_ck, b_bil_ck, co) end when SUBERU try.(a, b, now - 1, a_bil_ck, b_bil_ck, co) else raise "Error" end } n1 = try.(0, 1, 0, bil_ck_init.dup, bil_ck_init.dup, 0) n2 = try.(1, 0, 0, bil_ck_init.dup, bil_ck_init.dup, 0) puts n1 || n2 ? [n1, n2].compact.min : "NA" end
再帰版もWA。
KABE = 0 HASHIGO = 1 SUBERU = 2 loop do n = gets.to_i break if n.zero? bils = Array.new(2) { gets.split.map(&:to_i) } bil_ck_init = Array.new(n) stack = [[0, 0, bil_ck_init.dup, bil_ck_init.dup, 0], [1, 0, bil_ck_init.dup, bil_ck_init.dup, 0]] result = Float::INFINITY while (tmp = stack.pop) bil, now, a_bil_ck, b_bil_ck, co = tmp loop do break if a_bil_ck[now] a_bil_ck[now] = true if now >= n - 1 && bils[bil][now] != SUBERU result = [result, co].min break end jump = ->{ stack << [1 - bil, now + 2, b_bil_ck, a_bil_ck, co + 1] if now + 2 < n stack << [1 - bil, now + 1, b_bil_ck, a_bil_ck, co + 1] if now + 1 < n stack << [1 - bil, now, b_bil_ck, a_bil_ck, co + 1] } case bils[bil][now] when KABE jump.() break when HASHIGO if bils[bil][now + 1] != HASHIGO jump.() break else now += 1 end when SUBERU now -= 1 else raise "Error" end end end result = "NA" if result == Float::INFINITY puts result end
0231 Dangerous Bridge
loop do n = gets.to_i break if n.zero? persons = Array.new(n) { gets.split.map(&:to_i) } dp = Hash.new(0) persons.each do |m, a, b| dp[a] += m dp[b] -= m end weight = 0 result = "OK" dp.sort.each do |t, w| weight += w if weight > 150 result = "NG" break end end puts result end
0232 Life Game
素朴なDFS。TLE。
loop do x, y, z = gets.split.map(&:to_i) break if x + y + z == 0 vs = gets.split.map(&:to_i) nea = Array.new(z) { gets.split.map(&:to_i) } events = Array.new(y + 1, 0) nea.each do |n, e, a| events[n] = case e when 1 then a * 1000 when 2 then a when 3 then -a else raise "Error" end end q = [[0, 1.0, 0]] mean = 0 while (now = q.pop) pos, p, money = now next if pos >= y e = events[pos] if e >= 1000 q << [pos + e / 1000, p, money] next elsif e.nonzero? tmp = money + e money = [tmp, 0].max mean += p * e if money > 0 end p /= x vs.each do |step| q << [pos + step, p, money] end end puts mean.to_i end
0238 Time to Study
while true t = gets.to_i break if t.zero? n = gets.to_i sfs = Array.new(n) { gets.split.map(&:to_i) } dif = t - sfs.sum { |s, f| f - s } puts dif <= 0 ? "OK" : dif end
0239 Calorie Counting
while true n = gets.to_i break if n.zero? sweets = Array.new(n) { gets.split.map(&:to_i) } limit = gets.split.map(&:to_i) result = sweets.select {|swt| cal = [4, 9, 4].zip(swt[1, 3]).inject(0) { |acc, (a, b)| acc + a * b } [*swt[1, 3], cal].zip(limit).all? { |a, b| a <= b } } puts result.empty? ? "NA" : result.map { |e| e[0] } end
0240 Interest Rates
f1 = ->(y, r) { 1.0 + y * (r / 100.0) } f2 = ->(y, r) { (1.0 + r / 100.0) ** y } while true n = gets.to_i break if n.zero? y = gets.to_i banks = Array.new(n) { gets.split.map(&:to_i) } max = 0 bank_num = nil banks.each do |b, r, t| gold = [f1, f2][t - 1].call(y, r) if max < gold max = gold bank_num = b end end puts bank_num end
0241 Quaternion Multiplication
四元数の積を求める問題。実装は悩んだが、四元数をクラスにして、和と積を定義した。
class Q def initialize(r, i, j, k) @ary = [r, i, j, k] end attr_reader :ary def +(obj) Q.new(*ary.zip(obj.ary).map { |a, b| a + b }) end def *(obj) x = ary.product(obj.ary).map { |a, b| a * b } e = x.each_slice(4).to_a ans = Array.new(4) ans[0] = Q.new(*e[0]) ans[1] = Q.new(-e[1][1],e[1][0],-e[1][3],e[1][2]) ans[2] = Q.new(-e[2][2],e[2][3],e[2][0],-e[2][1]) ans[3] = Q.new(-e[3][3],-e[3][2],e[3][1],e[3][0]) ans.inject(:+) end end while true n = gets.to_i break if n.zero? data_n = Array.new(n) { gets.split.map(&:to_i) } puts data_n.map {|data| a = Q.new(*data[0, 4]) b = Q.new(*data[4, 4]) (a * b).ary.join(" ") } end
0242 Input Candidates
最初、問題の意図を読み違えていた。
while true n = gets.to_i break if n.zero? lines = Array.new(n) { gets.split } k0 = gets.chomp tally = Hash.new(0) lines.inject(:concat).each do |word| tally[word] += 1 end result = tally.select { |k, v| k.start_with?(k0) } .sort_by { |k, v| [-v, k] } .take(5) .map { |e| e[0] } .join(" ") puts result.empty? ? "NA" : result end
0243 Filling Game
頑張ったがTLE。Ruby では通過者なし。
def all?(field) tmp = field.join tmp[0..-2] == tmp[1..-1] end def copy(field) field.map { |row| row.dup } end def push_button(w, h, col0, field) checked = copy(field) q = [[0, 0]] while (po = q.shift) x, y = po checked[y][x] = "." col = field[y][x] field[y][x] = col0 [[1, 0], [0, -1], [-1, 0], [0, 1]].each do |dx, dy| x1 = x + dx y1 = y + dy next if x1 < 0 || y1 < 0 || x1 >= w || y1 >= h next if checked[y1][x1] == "." q << [x1, y1] if field[y1][x1] == col end end end while true x, y = gets.split.map(&:to_i) break if (x + y).zero? field0 = Array.new(y) { gets.split.join } if all?(field0) puts 0 next end table = %w(R G B) q = [] (table - [field0[0][0]]).each { |col| q << [col, 1, copy(field0)] } while (e = q.shift) col, n, field = e push_button(x, y, col, field) if all?(field) puts n break end (table - [field[0][0]]).each { |col| q << [col, n + 1, copy(field)] } end end