写出如下问题的C++代码:最优二分检索树问题,给定标识符集(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-01 12:50:27 浏览: 271
以下是最优二分检索树问题的C++代码,使用了动态规划算法。
```c++
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 110;
double p[MAXN], q[MAXN], w[MAXN][MAXN], d[MAXN][MAXN];
int root[MAXN][MAXN], ans[MAXN], cnt;
void print(int l, int r, int rt) {
if (l > r) return;
ans[cnt++] = root[l][r];
if (l == r) return;
print(l, root[l][r] - 1, root[l][r]);
print(root[l][r] + 1, r, root[l][r]);
}
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];
for (int i = 1; i <= n + 1; i++) {
w[i][i - 1] = q[i - 1];
d[i][i - 1] = q[i - 1];
}
for (int len = 1; len <= n; len++) {
for (int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
d[i][j] = 1e9;
for (int k = i; k <= j; k++) {
double tmp = d[i][k - 1] + d[k + 1][j] + w[i][j];
if (tmp < d[i][j]) {
d[i][j] = tmp;
root[i][j] = k;
}
}
}
}
cout << "最小期望搜索代价为:" << d[1][n] << endl;
print(1, n, 0);
cout << "最优二分检索树先根遍历得到的字符编号序列为:";
for (int i = 0; i < cnt; i++) cout << ans[i] << " ";
cout << endl;
return 0;
}
```
输入示例:
```
5
0.15 0.10 0.05 0.10 0.20
0.05 0.10 0.05 0.05 0.05 0.10
```
输出示例:
```
最小期望搜索代价为:2.75
最优二分检索树先根遍历得到的字符编号序列为:4 2 1 3 5
```
阅读全文