少し遅れましたが、ここで完全な解決策を探している人のために、以下は私のものです。最初に、動的プログラミング、メモ化、集計の意味を理解するために、https ://stackoverflow.com/a/6165124/4636721 の回答を読むことを他の人に提案します。
とにかく私の解決策については基本的に私たちは与えられた方法を持っています:
// Not efficient at all
private static double binomial(int N, int k, double p)
{
if (N == 0 && k == 0)
{
return 1.0;
}
else if ((N < 0) || (k < 0))
{
return 0.0;
}
else
{
return (1.0 - p) * binomial(N - 1, k, p) + p * binomial(N - 1, k - 1, p);
}
}
はい、これは本当に遅いです...再帰呼び出しの数はちょっと大きいです(約〜N ^ 2)
はい、基本的にはメモ化アプローチを使用できます。これは、基本的に他の人がすでに計算した値を基本的にキャッシュすることを述べているためです。一部の人々にとって、メモ化は再帰戦略を維持し、必要な値が計算されたかどうかを確認することを意味します。プログラムが計算してキャッシュする必要がない場合、実装は非常に簡単です。
private static double binomialTopDown(int N, int k, double p)
{
double[][] cache = new double[N + 1][k + 1];
for (int i = 0; i < (N + 1); i++)
{
Arrays.fill(cache[i], Double.NaN);
}
return binomialTopDown(N, k, p, cache);
}
// More efficient
private static double binomialTopDown(int N, int k, double p, double[][] cache)
{
if ((N == 0) && (k == 0))
{
return 1.0;
}
else if ((N < 0) || (k < 0))
{
return 0.0;
}
else if (Double.isNaN(cache[N][k]))
{
cache[N][k] = (1.0 - p) * binomialTopDown(N - 1, k, p, cache) + p * binomialTopDown(N - 1, k - 1, p, cache);
}
return cache[N][k];
}
秘訣は、実際にはボトムアップ アプローチ (集計とも呼ばれる) を使用して、より効率的な方法で計算を順序付けることです。これは通常、上記のアルゴリズムの反復バージョンを使用して実現されます。
// Much more efficient
private static double binomialBottomUp(int N, int k, double p)
{
/*
double[][] cache = new double[N + 1][k + 1];
cache[0][0] = 1.0;
for (int i = 1; i <= N; i++)
{
cache[i][0] = Math.pow(1.0 - p, i);
for (int j = 1; j <= k; j++)
{
cache[i][j] = p * cache[i - 1][j - 1] + (1.0 - p) * cache[i - 1][j];
}
}
return cache[N][k];
*/
// Optimization using less memory, swapping two arrays
double[][] cache = new double[2][k + 1];
double[] previous = cache[0];
double[] current = cache[1];
double[] temp;
previous[0] = 1.0;
for (int i = 1; i <= N; i++)
{
current[0] = Math.pow(1.0 - p, i);
for (int j = 1; j <= k; j++)
{
current[j] = p * previous[j - 1] + (1.0 - p) * previous[j];
}
temp = current;
current = previous;
previous = temp;
}
return previous[k];
}
これは、ボトムアップ アプローチで動的計画法を使用する最も効率的な方法です。
お役に立てれば。