安定したマージとF(i, j)
によって達成できる最大のペアワイズ和として定義します。Ai...An
Bj...Bn
マージの各ステップで、次の3つのオプションのいずれかを選択できます。
- の最初の2つの残りの要素を取り
A
ます。
- の最初の残りの要素
A
との最初の残りの要素を取りB
ます。
- の最初の2つの残りの要素を取り
B
ます。
したがって、F(i, j)
再帰的に次のように定義できます。
F(n, n) = 0
F(i, j) = max
(
AiAi+1 + F(i+2, j), //Option 1
AiBj + F(i+1, j+1), //Option 2
BjBj+1 + F(i, j+2) //Option 3
)
2つのリストの最適なマージを見つけるにはF(0, 0)
、単純に、中間値を何度も計算する必要がありますが、F(i, j)
見つかったときにそれぞれをキャッシュすることで、複雑さがに軽減されO(n^2)
ます。
これを行ういくつかの迅速で汚いc++は次のとおりです。
#include <iostream>
#define INVALID -1
int max(int p, int q, int r)
{
return p >= q && p >= r ? p : q >= r ? q : r;
}
int F(int i, int j, int * a, int * b, int len, int * cache)
{
if (cache[i * (len + 1) + j] != INVALID)
return cache[i * (len + 1) + j];
int p = 0, q = 0, r = 0;
if (i < len && j < len)
p = a[i] * b[j] + F(i + 1, j + 1, a, b, len, cache);
if (i + 1 < len)
q = a[i] * a[i + 1] + F(i + 2, j, a, b, len, cache);
if (j + 1 < len)
r = b[j] * b[j + 1] + F(i, j + 2, a, b, len, cache);
return cache[i * (len + 1) + j] = max(p, q, r);
}
int main(int argc, char ** argv)
{
int a[] = {2, 1, 3};
int b[] = {3, 7, 9};
int len = 3;
int cache[(len + 1) * (len + 1)];
for (int i = 0; i < (len + 1) * (len + 1); i++)
cache[i] = INVALID;
cache[(len + 1) * (len + 1) - 1] = 0;
std::cout << F(0, 0, a, b, len, cache) << std::endl;
}
合計だけでなく実際のマージされたシーケンスが必要な場合は、どちらp, q, r
が選択されたかをキャッシュしてバックトラックする必要もあります。