给定标识符集(a 1 , a 2 , …a n ),这些字符的下标从1开始按自然序编号,p i 是对a i 成功检索的概率, q i 是不成功检索的概率, 且∑ (1<=i<=n) p i +∑ (0<=i<=n) q i =1,问:它的最优二分检索树是怎样的? 输入格式: 第1行是n,表示字符个数; 第2行是这n个字符的成功检索概率p i , 0<p i <1; 第3行是失败检索概率q i ,0<q i <1,且∑ (1<=i<=n) p i +∑ (0<=i<=n) q i =1。
时间: 2024-03-17 18:41:36 浏览: 53
这是一个经典的动态规划问题,可以使用动态规划算法解决。
具体实现方法如下:
首先,定义一个二维数组 dp,其中 dp[i][j] 表示从 i 到 j 的子树的最小搜索代价。
然后,我们可以使用以下递归式来计算 dp[i][j]:
dp[i][j] = min(dp[i][k-1] + dp[k+1][j] + w[i][j]),其中 i <= k <= j,w[i][j] 表示从 i 到 j 的概率之和。
最后,我们可以使用一个二维数组 root,其中 root[i][j] 表示从 i 到 j 的子树的根节点。我们可以使用以下递归式来计算 root[i][j]:
root[i][j] = k,其中 i <= k <= j 且 dp[i][j] = dp[i][k-1] + dp[k+1][j] + w[i][j]。
最优解为 dp[1][n],根节点为 root[1][n]。
下面是完整的 C++ 代码实现:
```
#include <iostream>
#include <vector>
using namespace std;
const int MAXN = 100;
double p[MAXN], q[MAXN], w[MAXN][MAXN];
double dp[MAXN][MAXN];
int root[MAXN][MAXN];
void optimal_bst(int n) {
for (int i = 1; i <= n; i++) {
dp[i][i-1] = q[i-1];
w[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;
dp[i][j] = 1e9;
w[i][j] = w[i][j-1] + p[j] + q[j];
for (int k = i; k <= j; k++) {
double cost = dp[i][k-1] + dp[k+1][j] + w[i][j];
if (cost < dp[i][j]) {
dp[i][j] = cost;
root[i][j] = k;
}
}
}
}
}
void print_tree(int i, int j, int parent) {
if (i > j) {
cout << "d" << parent << " ";
return;
}
int k = root[i][j];
cout << "k" << k << " ";
print_tree(i, k-1, k);
print_tree(k+1, j, k);
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> p[i];
}
for (int i = 0; i <= n; i++) {
cin >> q[i];
}
optimal_bst(n);
cout << "Minimum cost: " << dp[1][n] << endl;
cout << "Optimal BST: ";
print_tree(1, n, 0);
cout << endl;
return 0;
}
```
阅读全文