UVA10304-Optimal Binary Search Tree(最优二分检索树)

该博客介绍了如何解决UVA10304问题,即找到最优二叉搜索树,使得查询频率高的元素更接近根节点。文章讨论了输入输出格式,并提供了两种解题思路:一种是基于四边形不等式的O(n^3)解决方案,另一种是更快的O(n^2)解决方案。
摘要由CSDN通过智能技术生成

Optimal Binary Search Tree

Given a set S = (e1, e2, …, en) of n distinct elements such that e1 < e2 < … < en and considering a
binary search tree (see the previous problem) of the elements of S, it is desired that higher the query
frequency of an element, closer will it be to the root.
The cost of accessing an element ei of S in a tree (cost(ei)) is equal to the number of edges in the
path that connects the root with the node that contains the element. Given the query frequencies of the
elements of S, (f(e1), f(e2), … , f(en)), we say that the total cost of a tree is the following summation:
f(e1) ∗ cost(e1) + f(e2) ∗ cost(e2) + … + f(en) ∗ cost(en)
In this manner, the tree with the lowest total cost is the one with the best representation for
searching elements of S. Because of this, it is called the Optimal Binary Search Tree.
Input
The input will contain several instances, one per line.
Each line will start with a number 1 ≤ n ≤ 250, indicating the size of S. Following n, in the
same line, there will be n non-negative integers representing the query frequencies of the elements of
S: f(e1), f(e2), … , f(en), 0 ≤ f(ei) ≤ 100. Input is terminated by end of file.
Output
For each instance of the input, you must print a line in the output with the total cost of the Optimal
Binary Search Tree.
Sample Input
1 5
3 10 10 10
3 5 10 20
Sample Output
0
20
20

题目大意:最优排序二叉树(OBST)
解题思路:区间dp 动态规划,可以用四边形不等式优化时间复杂度,从 O(n

最优二分检索Optimal Binary Search Tree)是一种经典的数据结构,它是一种可以对键进行搜索的二叉,且中每个节点都有一个与之关联的数值,通常是一个键值和一个权值。它的主要特点是查询的时间复杂度为O(logn),效率非常高。同时,它可以通过动态规划的方法,构建出一棵,使得所有的查找操作所需的时间最小。 在C语言中,实现最优二分检索可以使用动态规划算法进行构建。其基本思路是:先按照给定的键值和权值构造一颗二叉搜索,然后计算出每个节点对应子的最小搜索代价,并选择最小代价来构造最优二分检索。通过动态规划的方法,可以将时间复杂度优化到O(n^3)。 下面是一个简单的C语言实现示例: ```c #include <stdio.h> #include <stdlib.h> #define MAX_N 100 int n; double p[MAX_N + 1]; // 数组p存储每个关键字被搜索到的概率 double q[MAX_N + 1]; // 数组q存储每个虚拟节点(即没有关键字)被搜索到的概率 double w[MAX_N + 1][MAX_N + 1]; // 数组w存储子i-j的概率和 double e[MAX_N + 1][MAX_N + 1]; // 数组e存储子i-j的最小代价 double root[MAX_N + 1][MAX_N + 1]; // 数组root存储子i-j最优二分检索的根节点 void optimal_bst() { for (int i = 1; i <= n + 1; i++) { w[i][i - 1] = q[i - 1]; e[i][i - 1] = q[i - 1]; } for (int len = 1; len <= n; len++) { for (int i = 1; i <= n - len + 1; i++) { int j = i + len - 1; e[i][j] = __DBL_MAX__; w[i][j] = w[i][j - 1] + p[j] + q[j]; for (int k = i; k <= j; k++) { double t = e[i][k - 1] + e[k + 1][j] + w[i][j]; if (t < e[i][j]) { e[i][j] = t; root[i][j] = k; } } } } } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%lf", &p[i]); q[i] = q[i - 1] + p[i]; } q[n + 1] = q[n]; optimal_bst(); printf("最小代价为:%lf\n", e[n]); printf("最优二分检索的根节点为:%lf\n", root[n]); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值