问题描述:你要查找n个字符,且已知n个字符要查找的概率,求最小比较次数。
解题思路:通过对n个字符构建最优二叉查找树->用动态规划的算法构建最优二叉查找树。
附上解题代码:
/*
*用动态规划求最优二叉查找树
*@Wison Chan
*2015/5/25
*
*/
#include<iostream>
using namespace std;
int main()
{
//代表有多少个节点
int n;
cin>>n;
//输入n个节点的查找概率数组
double* P=new double[n];
for(int i=0;i<n;++i)
cin>>P[i];
//创建节点数由1到n的最小平均查找次数数组
double** C=new double*[n+2];
for(int i=0;i<n+2;++i)
C[i]=new double[n+1];
//创建节点数由1到n的最优根节点
int** R=new int*[n+2];
for(int i=0;i<n+2;++i)
R[i]=new int[n+1];
//初始化
for(int i=1;i<n+1;++i)
{
//从i到i-1,无效,为0
C[i][i-1]=0;
//从P[i-1]到P[i-1],还是P[i-1]
C[i][i]=P[i-1];
//节点从i到i,所以根节点还是i
R[i][i]=i;
}
//数组最后一个
C[n+1][n]=0;
//遍历(1,2),(2,3),...,(n-1,n),(1,3),...
for(int d=1;d<n;++d)
{
for(int i=1;i<n-d+1;++i)
{
int j=i+d;
double min=1000;
//最优根节点
int kmin=0;
//k为可能最优根节点
for(int k=i;k<j+1;++k)
{
if(C[i][k-1]+C[k+1][j]<min)
{
min=C[i][k-1]+C[k+1][j];
kmin=k;
}
}
R[i][j]=kmin;
//找出i到j的概率和
double sum=P[i-1];
for(int s=i+1;s<j+1;++s)
sum+=P[s-1];
//递推公式
C[i][j]=min+sum;
}
}
//输出节点为1到n的最小平均查找概率,以及最优根节点
cout<<C[1][n]<<" "<<R[1][n]<<endl;
system("pause");
return 0;
}