動的計画法(DP)を考えます。
データ
d p [ i ] [ j ] [ k ] : = dp[i][j][k]:= d p [ i ] [ j ] [ k ] := {その状態になるのが可能であるかどうか 0 or 1}
i : i: i : 今までに1つ以上のグループを選んだか(0 or 1)
j : j: j : j j j 個目のグループを見た時
k : k: k : ( 男性 − 女性 ) (男性-女性) ( 男性 − 女性 ) の値
遷移
d p [ i ] [ j ] [ k ] dp[i][j][k] d p [ i ] [ j ] [ k ] が 1 1 1 のとき
j j j 個目のグループを選ばなかったとき : d p [ i ] [ j + 1 ] [ k ] = 1 : dp[i][j+1][k] = 1 : d p [ i ] [ j + 1 ] [ k ] = 1
j j j 個目のグループを選んだ時 : d p [ m i n ( 1 , i + 1 ) ] [ j + 1 ] [ k + ( A [ j ] − B [ j ] ) ] = 1 : dp[\mathrm{min}(1,i+1)][j+1][k+(A[j]-B[j])] = 1 : d p [ min ( 1 , i + 1 )] [ j + 1 ] [ k + ( A [ j ] − B [ j ])] = 1
考えられる ( 男性 − 女性 ) (男性-女性) ( 男性 − 女性 ) の値をすべて網羅するため、k k k の範囲を − 10000 ~ 10000 -10000 ~ 10000 − 10000 ~ 10000 程にしておくとよいでしょう。
【別解】
愚直なアルゴリズムとして、たとえば以下のようなものが思いつきます。
疑似コード S := {} # 空のset
for a, b <- A, B: # a, bの各要素をそれぞれa, bとして列挙する。
T := S # SをTにコピーする
T |= { 0 } # Tに0を入れる
for t <- T: # Tの各要素をtとして列挙する。
S |= { t + a - b } # Sに t + (a - b) を挿入する
print S.map(abs).min() # 答えは、ノルムが最小になるようなSの要素
実は、このアルゴリズムは w o r s t O ( N ( s u m ( A ) + s u m ( B ) ) l o g ( s u m ( A ) + s u m ( B ) ) ) \mathrm{worst O}(N (\mathrm{sum}(A)+ \mathrm{sum} (B)) \mathrm{log} (\mathrm{sum}(A) + \mathrm{sum}(B))) worstO ( N ( sum ( A ) + sum ( B )) log ( sum ( A ) + sum ( B ))) 時間 で作動します。(任意の集合への任意の要素の挿入は要素数に対する対数時間で行えるとします。)
S に属しうる要素の値が満たす条件として、たとえば以下のようなものが考えられます。
下界 : − ( s u m ( A ) + s u m ( B ) ) : -(\mathrm{sum}(A) + \mathrm{sum}(B)) : − ( sum ( A ) + sum ( B ))
上界 : s u m ( A ) + s u m ( B ) : \mathrm{sum}(A) + \mathrm{sum}(B) : sum ( A ) + sum ( B )
A − B { A - B } A − B からいくつかの値を重複を許さず選んだとき、総和を 最小 / 最大 化する問題を考えると明らかです。
ゆえに、S S S に属する元の個数は常に O ( s u m ( A ) + s u m ( B ) ) \mathrm{O}(\mathrm{sum(A)} + \mathrm{sum}(B)) O ( sum ( A ) + sum ( B )) 個です。