题目描述
T 是由有序集合S = {X ,X ……, X ) (X <X ……,<X) 构成的二叉搜索树 在其中查找某个值
- X ∈ (Xi, Xi+1) 的概率为 ai
- X = Xi 的概率为bi
规定 x0 = -∞ , Xn+1 = +∞ ,
存取分布概率
- 称 (a0 , b1 ,a1 , ….. , bn , an ) 为集合S的存取概率分布
平均路长
- 当S确定时具有平均最小路长的T就是对应的最优二叉树
递归求解最优值
定义
- W[i]: a0 + b1 + a1 + ……. + bi + ai
- w[i][j] : a + bi + ai + ……. + bj + aj
- a[i] : (xi-1, xi) 的存取概率
- b[i] : xi 的存取概率
- root[i][j] : 当子树为T时的根节点
- m[i][j] :当子树为T是后的
基础解
代码
/*
设 S={x1, x2, ···, xn} 是一个有序集合,且x1, x2, ···, xn表示有序集合的二叉搜索树利用二叉树的顶点存储有序集中的元素,而且具有性质:存储于每个顶点中的元素x 大于其左子树中任一个顶点中存储的元素,小于其右子树中任意顶点中存储的元素。
最优二叉树就是平均路长最小的数
*/
#include<stdio.h>
#include<stdlib.h>
const int N = 100;
double w[N][N];//w[i][j]=ai-1 + bi + .... + bj + aj
double m[N][N];//m[i][j] = w[i][j]P(ij)
int n;//元素个数
double a[N];//失败概率
double b[N];//失败概率
int root[N][N];//当子树Tij 最优时候的根节点在S中的下标
int q = 0;
double W[N];
//显示解的树形结构
void showTree(int l,int r,int deep) {
if (l > r) {
for (int i = 0; i < deep; i++) {
printf("-");
}
printf("q%d\n",q++);
return;
}
for (int i = 0; i < deep; i++) {
printf("-");
}
printf("%d\n",root[l][r]);
showTree(l, root[l][r] - 1, deep + 1);
showTree( root[l][r] + 1,r, deep + 1);
}
//计算 a[i-1] + b[i] + a[i] + ..... + b[j] + a[h]
double getW(int i, int j) {
return W[j] - W[i - 1] + a[i - 1];
}
int main() {
//输入
scanf("%d", &n);
scanf("%lf", &a[0]);//输入a0
W[0] = a[0];
for (int i = 1; i <=n; i++) { // b1 , a1, ... bn , an
scanf("%lf", &b[i]);
scanf("%lf", &a[i]);
W[i] = W[i - 1] + a[i] + b[i];//用来求解区间和
}
//初始化 当非叶节点个数为1时
for (int i = 1; i <= n; i++) {
w[i][i] = a[i - 1] + a[i] + b[i];
m[i][i] = w[i][i];
root[i][i] = i;
}
//动态规划
for (int r = 2; r <= n; r++) {//子树非叶节点个数
for (int i = 1; i <= n - r + 1; i++) {//子树起点
int j = i + r - 1;//子树终点
root[i][j] = i;
m[i][j] = 0xFFFFFF;
for (int k = i; k <= j; k++) {//轮流作为根节点
if (m[i][j] > getW(i,j) + m[i][k - 1] + m[k + 1][j]) {
root[i][j] = k;
m[i][j] = getW(i, j) + m[i][k - 1] + m[k + 1][j];
}
}
}
}
//输出最短平均路径m[1][n]
printf("%.2lf\n", m[1][n]);
//表达树
showTree(1,n,1);
return 0;
}
- 输入样例
3
0.15 0.5 0.1 0.1 0.05 0.05 0.05
- 输出
1.50
-1
—q0
—2
—-q1
—-3
——q2
——q3
#include<stdio.h>
#include<stdlib.h>
const int N = 100;
double w[N][N];//w[i][j]=ai-1 + bi + .... + bj + aj
double m[N][N];//m[i][j] = w[i][j]P(ij)
int n;//元素个数
double a[N];//失败概率
double b[N];//失败概率
int root[N][N];//当子树Tij 最优时候的根节点在S中的下标
int q = 0;
double W[N];//用来区间求和 w[i][j] = a[i-1] + b[i] + a[i] + ..... + b[j] + a[h] = W[j] - W[i - 1] + a[i - 1]
void showTree(int l,int r,int deep) {
if (l > r) {
for (int i = 0; i < deep; i++) {
printf("-");
}
printf("q%d\n",q++);
return;
}
for (int i = 0; i < deep; i++) {
printf("-");
}
printf("%d\n",root[l][r]);
showTree(l, root[l][r] - 1, deep + 1);
showTree( root[l][r] + 1,r, deep + 1);
}
//计算 a[i-1] + b[i] + a[i] + ..... + b[j] + a[h]
double getW(int i, int j) {
return W[j] - W[i - 1] + a[i - 1];
}
int main() {
//输入
scanf("%d", &n);
scanf("%lf", &a[0]);//输入a0
W[0] = a[0];
for (int i = 1; i <=n; i++) { // b1 , a1, ... bn , an
scanf("%lf", &b[i]);
scanf("%lf", &a[i]);
W[i] = W[i - 1] + a[i] + b[i];
}
//查看输入
printf("\n");
printf("a : ");
for (int i = 0; i <= n; i++) {
printf("%.2lf ", a[i]);
}
printf("\n");
printf("b : ");
for (int i = 1; i <= n; i++) {
printf("%.2lf ", b[i]);
}
printf("\n");
//初始化
for (int i = 1; i <= n; i++) {
w[i][i] = a[i - 1] + a[i] + b[i];//
m[i][i] = w[i][i];
root[i][i] = i;
}
//动态规划
for (int r = 2; r <= n; r++) {//子树非叶节点个数
for (int i = 1; i <= n - r + 1; i++) {//子树起点
int j = i + r - 1;//子树终点
root[i][j] = i;
m[i][j] = 0xFFFFFF;
for (int k = i; k <= j; k++) {//轮流作为根节点
if (m[i][j] > getW(i,j) + m[i][k - 1] + m[k + 1][j]) {
root[i][j] = k;
m[i][j] = getW(i, j) + m[i][k - 1] + m[k + 1][j];
}
}
}
}
//输出最短平均路径m[1][n]
printf("%.2lf\n", m[1][n]);
//显示w 和 m
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
printf("%.2lf ", m[i][j]);
}
printf("\n");
}
printf("\n"); printf("\n");
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
printf("%4.2lf ", getW(i,j));
}
printf("\n");
}
//表达树
showTree(1,n,1);
return 0;
}
作业 :
- 1.设n=4,有序集为k1, k2, k3, k4,存取概率设b(1 : 4)=(3, 3, 1, 1)和a(0 : 4)=(2,3,1,1,1)写出构造最优二叉搜索树的过程。
输入 :
4 2 3 3 3 1 1 1 1 1
输出 :
注意:b,a都乘了16。