思路可見:https://blog.csdn.net/a1439775520/article/details/96769471。這篇寫得非常清晰。
//動態規劃
class 最優二叉搜索樹問題 {
public static void getBestTree(int n,double p[],double res[][],int m[][])
{ /*p記錄1到n個結點的查找概率,p[0]無意義,其角標從1到n
n是n個字符,
res[i][j]記錄最優子樹的查找子樹,
m[i][j]記錄i到j間最優子樹的根結點
*/
for(int i=1;i<n;i++)
{
//初始化主表
res[i][i-1]=0;
res[i][i]=p[i];
//初始化根表
m[i][i]=i;//就i這個結點,那麼最優的根結點就是它本身。
}
res[n][n-1]=0;
for(int d=1;d<n-1;d++)
{
for(int i=1;i<n-d;i++)
{
int j=i+d;
double minvalue=Double.MAX_VALUE;
for( int k=i;k<=j;k++)//利用公式在i到j間找到最優的根結點k。
{
if(res[i][k-1]+res[k+1][j]<minvalue)
{
minvalue=res[i][k-1]+res[k+1][j];
m[i][j]=k;
}
}
double sum=0;
for(int q=i;q<=j;q++)
{
sum+=p[q];
}
res[i][j]=minvalue+sum;
}
}
}
public static void Print(double d[][],int n)
{
for(int i=1;i<=n;i++)
{
for(int j=0;j<n;j++)
{
System.out.print(d[i][j]+" ");
}
System.out.println();
}
}
public static void Print(int d[][],int n)
{
for(int i=1;i<=n;i++)
{
for(int j=0;j<n;j++)
{
System.out.print(d[i][j]+" ");
}
System.out.println();
}
}
public static void main(String[] args)
{
int n=5;
double[] p={0,0.1,0.2,0.4,0.3};
double res[][]=new double[n+1][n];//記錄最優子樹的查找次數。i從1到n,j從0到n-1。
int m[][]=new int[n+1][n];//記錄最優根結點
getBestTree(n,p,res,m);
Print(res,n);
System.out.println("**********************");
Print(m,n);
}
}