package com.dynamic;
import java.text.DecimalFormat;
public class OptimalSearchTree {
private double [] p;//关键字概率
private double [] q;//不在树中的关键字概率
private int [] k;//关键字
//private int [][]d;//不在树中的关键字
private double[][]e;
private double[][]w;
private int[][]root;
public OptimalSearchTree(int[]k,double [] p,double []q)throws Exception{
if(k.length+1!=p.length){
throw new Exception("数据错误");
}
if(k.length+1!=q.length){
throw new Exception("数据错误");
}
double sum=0;
for(int i=0;i<p.length;i++){
sum+=p[i];
}
for(int j=0;j<q.length;j++){
sum+=q[j];
}
DecimalFormat format=new DecimalFormat("0.00");
if(Double.parseDouble(format.format(sum))!=1.0){
throw new Exception("数据错误");
}
this.q=q;
this.p=p;
this.k=k;
e=new double[p.length+1][p.length+1];
w=new double[p.length+1][p.length+1];
root=new int[p.length][p.length];
for(int i=0;i<w.length;i++){
for(int j=0;j<w[i].length;j++){
w[i][j]=-1;
}
}
for(int i=0;i<e.length;i++){
for(int j=0;j<e[i].length;j++){
e[i][j]=Integer.MAX_VALUE;
}
}
}
private double innerOptimal(int i,int j){
if(e[i][j]!=Integer.MAX_VALUE){
return e[i][j];
}
if(j==i-1){
e[i][j]=q[i-1];
}else{
double tmp=Integer.MAX_VALUE;
for(int r=i;r<=j;r++){
tmp=innerOptimal(i,r-1)+innerOptimal(r+1,j)+computeW(i,j);
if(tmp<e[i][j]){
e[i][j]=tmp;
root[i][j]=r;
}
}
}
return e[i][j];
}
private double computeW(int i,int j){
if(w[i][j]>=0){
return w[i][j];
}else{
double tmp=0;
for(int l=i;l<=j;l++){
tmp+=p[l];
}
for(int l=i-1;l<=j;l++){
tmp+=q[l];
}
w[i][j]=tmp;
return tmp;
}
}
public void printTree(){
innerPrintTree(1,k.length,-1);
}
private void innerPrintTree(int i,int j,int parent){
if(i>j){
return;
}
if(i==1&&j==k.length){
System.out.println(" "+root[i][j]);
}else{
System.out.println(root[i][j]+","+parent);
}
innerPrintTree(i,root[i][j]-1,root[i][j]);
innerPrintTree(root[i][j]+1,j,root[i][j]);
}
public double optimal(){
double ret=innerOptimal(1,k.length);
return ret;
}
public static void main(String[] args) throws Exception{
int [] k=new int[]{1,2,3,4,5};
double [] p=new double[]{0,0.15,0.10,0.05,0.10,0.20};
double [] q=new double[]{0.05,0.10,0.05,0.05,0.05,0.10};
OptimalSearchTree ost=new OptimalSearchTree(k,p,q);
System.out.println(ost.optimal());
ost.printTree();
}
}