50時間以内に解けるかな?
Posted: 2012年5月22日(火) 03:42
長さnの数列Aと整数Mに対して、Aの要素の中のいくつかの要素を足しあわせてMが作れるかどうかを判定するプログラムを作成せよ。
Aの各要素は1度だけ使うことができる。
数列Aが与えられたうえで、質問としてq個のMが与えれるので、それぞれについて"yes"または"no"と出力せよ。
プログラムはC, C++, JAVA, C++11, C#, Dいずれかの言語で作成すること。
入力
1行目にn、2行目にAを表すn個の整数、3行目にq、4行目にq個の整数Miが与えられる。
出力
各質問についてAの要素を足しあわせてMiを作ることができればyesと、できなければnoと出力せよ。
制約
n ≤ 20
q ≤ 200
1 ≤ Aの要素 ≤ 2000
1 ≤ Mi ≤ 2000
入力例 1
5
1 5 7 10 21
8
2 4 17 8 22 21 100 35
出力例 1
no
no
yes
yes
yes
yes
no
no
ヒント!
この問題は、総当たり探索によって解くことができる。
solve(p, t)をp番目以降の要素を使ってtを作れるかを判定する関数とすれば:
solve(0, M)
solve(1, M-{1番目より前の数を使ってできた和})
solve(2, M-{2番目より前の数を使ってできた和})
...
を再帰的に呼び出して検証すればよい。
各再帰関数においてp番目の要素を使った場合・使わなかった場合で2つの再帰関数を呼ぶ。
つまり、solve(p, t)においてsolve(p+1, t-A[p]), solve(p+1, t)が可能かを検証すれば全ての組み合わせを試すことができる。
Aの各要素は1度だけ使うことができる。
数列Aが与えられたうえで、質問としてq個のMが与えれるので、それぞれについて"yes"または"no"と出力せよ。
プログラムはC, C++, JAVA, C++11, C#, Dいずれかの言語で作成すること。
入力
1行目にn、2行目にAを表すn個の整数、3行目にq、4行目にq個の整数Miが与えられる。
出力
各質問についてAの要素を足しあわせてMiを作ることができればyesと、できなければnoと出力せよ。
制約
n ≤ 20
q ≤ 200
1 ≤ Aの要素 ≤ 2000
1 ≤ Mi ≤ 2000
入力例 1
5
1 5 7 10 21
8
2 4 17 8 22 21 100 35
出力例 1
no
no
yes
yes
yes
yes
no
no
ヒント!
この問題は、総当たり探索によって解くことができる。
solve(p, t)をp番目以降の要素を使ってtを作れるかを判定する関数とすれば:
solve(0, M)
solve(1, M-{1番目より前の数を使ってできた和})
solve(2, M-{2番目より前の数を使ってできた和})
...
を再帰的に呼び出して検証すればよい。
各再帰関数においてp番目の要素を使った場合・使わなかった場合で2つの再帰関数を呼ぶ。
つまり、solve(p, t)においてsolve(p+1, t-A[p]), solve(p+1, t)が可能かを検証すれば全ての組み合わせを試すことができる。