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;

}

你可能感兴趣的:(Binary search)