『問題解決のための「アルゴリズム×数学」が基礎からしっかり身につく本』の問題ID:009
が自力では解けなかったので復習。
なお、書籍名が長いので勝手に著者のidから取ってe8本と読んでいる。
問題
問題文
N 枚のカードが横一列に並べられています。左から i 番目 (1≤i≤N) のカードには整数 A
iが書かれています。
カードの中からいくつかを選んで、合計がちょうど S となるようにする方法はありますか。
制約
1≤N≤60
1≤A
i≤10000
1≤S≤10000
入力はすべて整数
回答
n, s = gets.chomp.split.map(&:to_i)
a = gets.chomp.split.map(&:to_i)
n.times do |i|
if a.combination(i).to_a.map(&:sum).include?(s)
puts 'Yes'
exit
end
end
puts 'No'
デバッグしながら考える
入力例1で考える
# 入力
3 11
2 5 9
Array#combination
n = 3
s = 11
a = [2, 5, 9]
# Enumeratorクラスのオブジェクトが返ってくる
n.times do |i|
pp a.combination(i)
end
# <Enumerator: ...>
# <Enumerator: ...>
# <Enumerator: ...>
# to_aを用いてarrayに変換
n.times do |i|
pp a.combination(i).to_a
end
# [[]]
# [[2], [5], [9]]
# [[2, 5], [2, 9], [5, 9]]
# 合計が必要なので合計の配列をつくる
n.times do |i|
pp a.combination(i).to_a.map(&:sum)
end
# [0]
# [2, 5, 9]
# [7, 11, 14]
# sが含まれているか確認
# 返り値がbooleanなことに注意
n.times do |i|
if a.combination(i).to_a.map(&:sum).inclide?(s)
puts 'Yes'
# 見つかったら抜ける
exit
end
end
puts 'No'