算法学习之动态规划(求矩阵连乘最小相乘次数)
基本思想:动态规划算法与分治法类似,其基本思想是将带求解的问题划分成若干个独立子问题,根据求得子问题的解合并而得到原问题的解。而动态规划划分的子问题往往不是相互独立的,因此若采用同分治法相同的求解问题的方法会导致大量的子问题被重复计算,为了避免这种情况发生,我们可以用一个表来记录我们求得的子问题的解,无论该子问题的解以后是否会用到,只要被计算,就将其填入表中。这便是动态规划的基本思想。
求解的基本步骤:
(1)找出最优解的性质,并刻画其结构特征。
(2)递归的定义最优值。
(3)以自底向上的方式计算出最优值。
(4)根据计算最优值时得到的信息,构造最优解。
时间、精力和水平有限,无法给出专业详细地分析,但我会把自己掌握的部分毫无保留分享给大家。
下面的程序我尽可能给出最详细的注释,如有错误还请及时指出,以避免产生没必要的误会。
#include<iostream>//数组p存储连乘矩阵的维数intp[]={30,35,35,15,15,5,5,10,10,20,20,25};intpcount=sizeof(p)/sizeof(*p);//二维数组m存放所有子问题的最优值intm[6][6];//二维数组s存放断开的位置kints[6][6];//用于打印二维数组voiddebug(intarray[][6]);//预初始化二维数组voidinitialization(intarray[][6]);//打印最优解的构成voidTraceback(inti,intj,intarray[][6]);//根据自底向上的方式计算所有子问题最优值voidMatrixChain(int*p,intn,intm[][6],ints[][6]){initialization(m);initialization(s);//注意n/2得到的是相乘矩阵的个数for(inti=0;i<n/2;i++)m[i][i]=0;//单个矩阵最优值为0//外层循环,从矩阵A1-A5依次计算矩阵链长度为2,3,4,5for(intr=1;r<n/2;r++)//内层循环,计算矩阵链长度为x(x可能为2,3,4,5)的所有值(例如:若x=2,//则计算m[1][2],m[2][3],m[3][4],m[4][5],m[5][6])for(inti=0;i<n/2-r;i++)//随矩阵链长度x增加,i的最大值与(n/2-r)//构成对应关系{intj=i+r;//列数j取决于矩阵链长度和行数im[i][j]=m[i+1][j]+p[2*i]*p[2*i+1]*p[j*2+1];//这里先求出一个基本解,以A0矩阵划分(A[0]*A[1:5])//std::cout<<"m"<<"["<<i<<"]"<<"["<<j<<"]"<<m[i][j]<<std::endl;s[i][j]=i;//保存划分的位置,Trackback求最优解用到for(intk=i+1;k<j;k++)//对每个可能划分的位置进行检索{intt=m[i][k]+m[k+1][j]+p[2*i]*p[2*k+1]*p[2*j+1];//求最优值的递推式//如果计算得到的值比基本解更优,那么替换原来的最优值和划分位置if(t<m[i][j]){m[i][j]=t;s[i][j]=k;}}}}voiddebug(intarray[][6]){for(inti=0;i<6;i++){for(intj=0;j<6;j++)std::cout<<array[i][j]<<"";std::cout<<std::endl;}}voidinitialization(intarray[][6]){for(inti=0;i<6;i++)for(intj=0;j<6;j++)array[i][j]=-1;}voidTraceback(inti,intj,intarray[][6]){usingstd::cout;usingstd::endl;if(i==j)return;Traceback(i,array[i][j],array);Traceback(array[i][j]+1,j,array);cout<<"MultiplyA"<<i<<","<<array[i][j];cout<<"andA"<<(array[i][j]+1)<<","<<j<<endl;}//一小段测试程序,不懂请尽可能多调试以便理解。intmain(){MatrixChain(p,pcount,m,s);debug(m);//debug(s);Traceback(1,5,s);return0;}
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。