pintia 7-25 最优二叉搜索树
输出格式:
第一行输出最小 m ,保留两位小数。
第二行先序遍历输出二叉树,对于实结点输出其编号,对于虚结点输出.,每一个符号后有一个空格,若有多个满足要求的二叉树,则输出根节点编号最小的。
输入样例:
3
0.50 0.1 0.05
0.15 0.1 0.05 0.05
输出样例:
1.50
1 . 2 . 3 . .
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
const int M = 100;
double C[M][M], W[M][M], p[M], q[M];
int S[M][M];
int n, i, j, k;
void Optimal_BST()
{
for (i = 1; i <= n; i++)
{
C[i][i - 1] = 0.0;
W[i][i - 1] = q[i - 1];
}
for (int t = 1; t <= n; t++)
{
for (i = 1; i <= n - t + 1; i++)
{
j = i + t - 1;
W[i][j] = W[i][j - 1] + p[j] + q[j];
C[i][j] = C[i][i - 1] + C[i + 1][j];
S[i][j] = i;
// 选取i+1到j之间的某个下标的关键字作为i到j的根,如果组成的期望值最小
// 则k为i到j的根结点
for (k = i + 1; k < j; k++)
{
double tmp = C[i][k - 1] + C[k + 1][j];
if (tmp < C[i][j] && fabs(tmp - C[i][j])>1E-6)
{
C[i][j] = tmp;
S[i][j] = k; // 记录i到j结点的树根
}
}
C[i][j] += W[i][j];
}
}
}
void Construct_Optimal_BST(int i, int j, bool flag)
{
if (flag == 0)
{
cout << S[i][j] << " ";;
flag = 1;
}
int k = S[i][j];
// 如果左子树是叶子
if (k - 1 < i)
{
cout << "." << " ";;
}
else
{
cout << S[i][k - 1] << " ";;
Construct_Optimal_BST(i, k - 1, 1);
}
// 如果右子树是叶子
if (k >= j)
{
cout << "." << " ";;
}
else
{
cout << S[k + 1][j] << " ";;
Construct_Optimal_BST(k + 1, j, 1);
}
}
int main()
{
cin >> n;
for (i = 1; i <= n; i++)
{
cin >> p[i];
}
for (i = 0; i <= n; i++)
{
cin >> q[i];
}
Optimal_BST();
cout << fixed << setprecision(2) << C[1][n] << endl;
Construct_Optimal_BST(1, n, 0);
system("pause");
return 0;
}