ITA 动态规划2

来源:互联网 发布:300出装软件 编辑:程序博客网 时间:2024/05/16 10:36

这个题目比较难想象,因为数组下标(表格的标号)跟问题之间的关系不像之前的问题那么的明确,一个推出一个。要注意的是,e[i,j]保存在表e[1...n+1,0...n]中,第一维下标到n+1是因为有一个包含虚拟键dn的子树,我们需要计算和保存e[n+1,n]。第二维下标从0开始,是为了保存e[1,0],需要画出一个树的格式,帮助理解这些概念。所有e[i,i-1]都是包含虚拟键的



//动态规划,最优二叉查找树//假设正在设计一个程序,用于将文章从英文翻译为法语,对于出现在文章内的每一个英文单词,//需要查看与它等价的法语。执行这些搜索操作的一种方式是建立一棵二叉查找树,,,//因为要为文章中的每个单词搜索这棵树,古故希望搜索所花费的总时间尽可能的小,//因此我们希望文章中出现频繁的单词呗放置在距离根部较近的地方,而且文章中可能会有些单词没有法语的翻译,//这些单词可能根本就不会出现在二叉查找树中。////  n个关键字,对于每个关键字ki,一次搜索ki的概率为pi,,,,//    树中还存在n+1个虚拟的关键字di,一尺搜索di的概率为qi,假设n=5个的关键字的集合上的二叉查找树的概率如下// ,现在要求根据上表构造一棵二叉查找树,使得二叉查找树的期望搜索代价最低://定义e[i,j]为搜索一棵包含关键字ki,,,kj的最优二叉查找树的期望代价,最终要计算e[1,n]。。。。////    当j=i-1时,只有虚拟键di-1,期望的搜索代价是e[i,i-1]=qi-1。////    当j>=i时,需要从ki,...,kj中选择一个根kr,然后用关键字ki,...,kr-1来构造一棵最优二叉查找树作为其左子树,//并用关键字kr+1,...,kj来构造一棵最优二叉查找树作为其右子树。。。注意当一棵树成为一个节点的子树时,//它的期望搜索代价增加量将为该子树中所有概率的总和。对于一棵有关键字ki,...,kj的子树,定义概率的总和为:////      w[i,j]=pl(l=i到j)的总和+ql(l=i-1到j的总和)////  因此,有////      e[i,j]=qi-1                                                         j=i-1////      e[i,j]=min{e[i,r-1]+e[r+1,j]+w[i,j]}                     i<=j////  另外定义root[i,j]为kr的下标r。const int n =5;double optimalBest(double p[], double q[], int root[][n+1]){int i=0,len=0,j=0,r=0;double t =0.0;double e[n+2][n+1];double w[n+2][n+1];for(i=1;i<=n+1;++i){e[i][i-1]=q[i-1];w[i][i-1]=q[i-1];}for(len=1; len <=n;++len)//内节点的个数{for(i=1;i<=n-len+1;++i)//设置起点i{j=i+len-1;//设置终点le[i][j]=0x7fffffff;w[i][j]= w[i][j-1]+p[j]+q[j];for(r=i;r<=j;++r){t=e[i][r-1]+e[r+1][j]+w[i][j];if(t<e[i][j]){e[i][j]=t;root[i][j]=r;cout<<"e"<<t<<endl;cout<<r<<endl;}}}}return e[1][n];}void printBest(int root[][n+1],int i,int j){int k=0;if(i<=j){cout<<root[i][j];k=root[i][j];printBest(root,i,k-1);printBest(root,k+1,j);}}int main(){int root[n+1][n+1];double p[n+1]={0,0.15,0.10,0.05,0.10,0.20};double q[n+1]={0.05,0.10,0.05,0.05,0.05,0.10};double k=optimalBest(p,q,root);cout<<"最小期望搜索代价:"<<k<<endl;printBest(root,1,n);}


0 0
原创粉丝点击