UVa 10304 Optimal Binary Search Tree(区间DP)

题意:

前提要了解什么是二叉查找树,然后再是最优二叉查找树。

最优二叉查找树是指,在二叉查找树的基础上,要求总的编码长度最小(类似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\n", dp[1][n]);
    }
    return 0;
}
posted @ 2012-11-19 19:01  kedebug  阅读(1440)  评论(0编辑  收藏  举报