問題解決力を鍛える!アルゴリズムとデータ構造を読み進めていく中で、二分探索法でAtCoderの射撃王という問題が出題されていました。
C++で解答が書かれていたがいまいちピンと来なかったので、Rubyで自分なりに解釈しながら書き換えていきました。
実際にACもらったので、コメントで説明してあるRubyコードを載せます。
n = gets.chomp.to_i
hs = Array.new(n) {gets.chomp.split(' ').map(&:to_i)}
#bsearchメソッドで二分探索開始(ブロックの評価結果が true になる最初の要素を返すか、nil を返す)
ans = (1..10**15).bsearch do |v|
# v は目標高度のデッドラインとなる
timetable = Array.new(n, 0)
flug = true
hs.each do |h, s|
#(v-h)/s で、風船がデッドラインに達するまでの時間
#風船がデッドラインに達するまでの時間と 最低限待てる時間を比べ、小さい方を選ぶ
second = [(v-h)/s, n-1].min
if second < 0
#風船のデッドラインまでの時間が負(既にデッドラインに達している)ならfalseにする
flug = false
else
##まだ正(デッドラインに達するまで時間がある)なら割らなきゃいけない時間の配列に+=1
timetable[second] += 1
end
end
shootable = 0
#shootable = その時間までで割れる風船の数
n.times do |j|
shootable += 1
#もしその時間までで割れる風船の数よりも多くの風船をその時間内に割らなきゃいけないなら、flug=false
flug = false if shootable < timetable[j]
#そうでないなら、割った数だけ引く
shootable -= timetable[j]
end
#flug = true ならvで与えたデッドライン以内で割れるということ
flug
end
#falseとtrueの境目のansが与えられる
p ans