样例1为:S=<A,B,C,D,E>
P=<0.04,0.1,0.02,0.3,0.02,0.1,0.05,0.2,0.06,0.1,0.01>
样例2为:S=<A,B,C,D>
P=<1,(3),3,(3),2,(1),1,(1),1> 加括号的值是结点的查找概率
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
char txt[]="ABCDEFGHIJKLMN";
double BST(int n,double *p,double *q,double c[20][20],double w[20][20],int r[20][20])
{//p为节点概率从1开始,q为空隙概率从0开始,c为最优检索成本,r为分界记录
for(int d=0;d<n;d++)
{
for(int i=0;i<n-d;i++)
{
int j=i+d+1;
w[i][j]=q[i];
for(int t=i+1;t<=j;t++)
w[i][j]+=q[t];
for(int t=j;t>j-d-1;t--)
w[i][j]+=p[t];
printf("W(%d,%d)=%lf\n",i,j,w[i][j]);
printf("C(%d,%d)=min{",i,j);
int R=i;//最优分界
double MIN=1e9;
for(int k=i+1;k<=j;k++)
{
printf("C(%d,%d)+C(%d,%d)",i,k-1,k,j);
if(c[i][k-1]+c[k][j]<MIN)
{
MIN=c[i][k-1]+c[k][j];
R=k;
}
if(k!=j)
printf(",");
}
c[i][j]=MIN+w[i][j];
printf("}+W(%d,%d)=%lf\n",i,j,c[i][j]);
r[i][j]=R;
printf("R(%d,%d)=%d\n\n",i,j,R);
}
}
return c[0][n];
}
void printTree(int L,int R,int r[20][20])
{
printf("%c",txt[r[L][R]-1]);
//左子树为T(L,r[L][R]-1) 右子树为T(r[L][R],R)
printf("(");
if(L!=r[L][R]-1)
printTree(L,r[L][R]-1,r);
printf(",");
if(r[L][R]!=R)
printTree(r[L][R],R,r);
printf(")");
}
int main(void)
{
{
puts("样例1");
double q[10]={0.04,0.02,0.02,0.05,0.06,0.01};
double p[10]={0,0.1,0.3,0.1,0.2,0.1};
double c[20][20]={0},w[20][20]={0};
int r[20][20]={0};
double ans=BST(5,p,q,c,w,r);
cout<<"最小花费为:"<<ans<<endl;
printTree(0,5,r);
cout<<endl;
}
{
puts("样例2");
double q[10]={1,3,2,1,1};
double p[10]={0,3,3,1,1};
double c[20][20]={0},w[20][20]={0};
int r[20][20]={0};
double ans=BST(4,p,q,c,w,r);
cout<<"最小花费为:"<<ans<<endl;
printTree(0,4,r);
cout<<endl;
}
return 0;
}