UVa 10304 Optimal Binary Search Tree(区間DP)
4149 ワード
タイトル:
二叉ルックアップツリーとは何かを理解し、次に最適な二叉ルックアップツリーを理解することを前提とします.
最適二叉ルックアップツリーとは、二叉ルックアップツリーに基づいて、総符号化長が最小(huffman符号化に類似)であることが要求される.
考え方:
非常に複雑に見えますが、実際には多くの細部を捨てて、ルートノードとして、その左右のサブツリーもきっと最適であることがわかります.
この考え方に基づいて,区間動的計画を自然に思い出し,小規模最適解から徐々に拡大することができる.
区間規模が大きくなると、新しいルートノードが選択され、区間にルートノードの左右を除いた最適解に高さが加算され、繰返し式があります.
k1 = max(k - 1, i),k2 = min(k + 1, j); (i <= k <= j) dp[i][j] = min(dp[i][j], dp[i][k1] + dp[k2][j] + sum[j] - sum[i-1] - a[k]);
前提条件は、a[]配列要素が増加/減少の順序を保つことです.
二叉ルックアップツリーとは何かを理解し、次に最適な二叉ルックアップツリーを理解することを前提とします.
最適二叉ルックアップツリーとは、二叉ルックアップツリーに基づいて、総符号化長が最小(huffman符号化に類似)であることが要求される.
考え方:
非常に複雑に見えますが、実際には多くの細部を捨てて、ルートノードとして、その左右のサブツリーもきっと最適であることがわかります.
この考え方に基づいて,区間動的計画を自然に思い出し,小規模最適解から徐々に拡大することができる.
区間規模が大きくなると、新しいルートノードが選択され、区間にルートノードの左右を除いた最適解に高さが加算され、繰返し式があります.
k1 = max(k - 1, i),k2 = min(k + 1, j); (i <= k <= j) dp[i][j] = min(dp[i][j], dp[i][k1] + dp[k2][j] + sum[j] - sum[i-1] - a[k]);
前提条件は、a[]配列要素が増加/減少の順序を保つことです.
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
const int MAXN = 256;
int dp[MAXN][MAXN];
int a[MAXN], sum[MAXN];
int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
for (int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
sum[0] = 0;
for (int i = 1; i <= n; ++i)
dp[i][i] = 0, sum[i] = sum[i-1] + a[i];
for (int p = 2; p <= n; ++p)
{
for (int i = 1, j = p; j <= n; ++i, ++j)
{
dp[i][j] = INT_MAX;
for (int k = i; k <= j; ++k)
{
int k1 = max(k - 1, i);
int k2 = min(k + 1, j);
dp[i][j] = min(dp[i][j], dp[i][k1] + dp[k2][j] + sum[j] - sum[i-1] - a[k]);
}
}
}
printf("%d
", dp[1][n]);
}
return 0;
}