AOJ(ALDS)その2

AIZU ONLINE JUDGE: Programming Challenge
 

ALDS1_9_A Complete Binary Tree

#完全二分木
$<.gets
given = [nil] + $<.gets.split.map(&:to_i)
a = nil
 
given.drop(1).each_with_index do |key, i|
  j = i + 1
  str = "node #{j}: key = #{key}, "
  str += "parent key = #{a}, " if (a = given[j / 2])
  str += "left key = #{a}, "   if (a = given[j * 2])
  str += "right key = #{a}, "  if (a = given[j * 2 + 1])
  puts str
end

 

ALDS1_9_B Maximum Heap

#最大ヒープ
h = $<.gets.to_i
given = [nil] + $<.gets.split.map(&:to_i)
 
max_heapify = ->(i) {
  l, r = i * 2, i * 2 + 1
  largest = (l <= h and given[l] > given[i]) ? l : i
  largest = r if r <= h and given[r] > given[largest]
  unless largest == i
    given[i], given[largest] = given[largest], given[i]
    max_heapify.(largest)
  end
}
 
(h / 2).downto(1) {|i| max_heapify.(i)}
puts given.drop(1).map {|i| " #{i}"}.join

 

ALDS1_9_C Priority Queue

#優先度付きキュー
class MaxHeap
  def initialize
    @heap = [nil]
    @size = 0
  end
   
  def insert(key)
    @heap << key
    @size += 1
    up_heap(@size / 2)
  end
   
  def up_heap(i)
    return if i.zero?
    l, r = i * 2, i * 2 + 1
    largest = (l <= @size and @heap[l] > @heap[i]) ? l : i
    largest = r if r <= @size and @heap[r] > @heap[largest]
    unless largest == i
      @heap[i], @heap[largest] = @heap[largest], @heap[i]
      up_heap(i / 2)
    end
  end
   
  def remove_root
    a = @heap[1]
    @heap[1] = @heap.pop
    @size -= 1
    down_heap(1)
    a
  end
   
  def down_heap(i)
    return if i > @size
    l, r = i * 2, i * 2 + 1
    largest = (l <= @size and @heap[l] > @heap[i]) ? l : i
    largest = r if r <= @size and @heap[r] > @heap[largest]
    unless largest == i
      @heap[i], @heap[largest] = @heap[largest], @heap[i]
      down_heap(largest)
    end
  end
end
 
 
h = MaxHeap.new
 
$<.readlines.map {|l| l.chomp.split}.each do |command|
  case command[0]
  when "insert" then h.insert(command[1].to_i)
  when "extract" then puts h.remove_root
  when "end" then break
  else raise "error"
  end
end

 

ALDS1_10_A Fibonacci Number

#フィボナッチ数列
fib = Enumerator.new do |y|
  a, b = 1, 1
  loop do
    y << a
    a, b = b, a + b
  end
end
 
puts fib.take($<.gets.to_i + 1).last

 

ALDS1_10_B: Matrix Chain Multiplication

連鎖行列積問題(Matrix-Chain Multiplication problem)。

INF = (1 << 31) - 1

n = gets.to_i
ms = n.times.map {gets.split.map(&:to_i)}

dp = Array.new(n + 1) {Array.new(n + 1, 0)}
dim = [ms[0][0]] + ms.map(&:last)

2.upto(n) do |l|
  1.upto(n - l + 1) do |i|
    j = i + l - 1
    dp[i][j] = INF
    i.upto(j - 1) do |k|
      tmp = dp[i][k] + dp[j][k] + dp[k + 1][j] + dim[i - 1] * dim[k] * dim[j]
      dp[i][j] = [dp[i][j], tmp].min
    end
  end
end

puts dp[1][n]

ここのパクリ。むずかしい。
※参考
連鎖行列積問題 - Qiita
動的計画法4 連鎖行列積 - Daily Tech Blog
連鎖行列積問題 : がぶ飲みミルク珈琲
※追記
わたしがパクったコードは、じつは『アルゴリズムイントロダクション 第3版 第2巻: 高度な設計と解析手法・高度なデータ構造・グラフアルゴリズム (世界標準MIT教科書)』のパクリだったことがわかった。