回顾分治法
- 当问题规模很小时容易求解
- 问题可分为子问题
- 子问题的解可合起来得到问题的解
- 子问题相互独立
动态规划
- 适用的问题前三点和分治法相同,不同的是应用动态规划求解的题一般子问题之间不独立,需要辅助空间记录子问题的值来减少求解次数
- 基本步骤:
1.找出最优解的性质,并描述其结构特征(最优子结构性质)(由子问题的最优解可以得到整个问题的最优解)
2.递归地定义最优值
3.以自底向上的方式计算出最优值
4.根据计算最优值时得到的信息,构造最优解
例子:矩阵连乘
给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2 ,…,n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。
例如:
A1={30x35} ; A2={35x15} ;A3={15x5} ;A4={5x10} ;A5={10x20} ;A6={20x25} ;
最后的结果为:((A1(A2A3))((A4A5)A6))
最小的乘次为15125。
//求连乘的最优值函数
//p数组记录n个矩阵的行列数 p0p1记录A1的 p1p2记录A2的
void MatrixChain(int *p,int n,int **m,int **s){
//s数组记录断开的位置(连乘的分界),是辅助构造最优解所使用的信息
for(int i=1;i<=n;i++) m[i][i]=0;
for(int r=2;r<=n;r++){
//确定了 i r ,就确定了一个子问题
for(int i=1;i<=n-r+1;i++){
//寻找最小值 并记录断开位置
int j=i+r-1;
m[i][j]=m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j];
s[i][j]=i;
for(int k=i+1;k<j;k++){
int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
if(t<m[i][j]){
m[i][j]=t;
s[i][j]=k;
}
}
}
}
}
//递归算法构造最优解
void Traceback(int i,int j,int **s){
if(i==j) return;
Traceback(i,s[i][j],s);
Traceback(s[i][j]+1,j,s);
cout<<i<<","<<s[i][j];
cout<<"and"<<s[i][j]+1<<","<<j<<endl;
}
算法复杂度分析:
此算法的计算量主要取决于子问题的数量,为O(n2);求每个子问题的最优值的复杂度为O(n);算法所用辅助空间为m,s数组,都是二维表,复杂度为O(n2)。
因此此算法的计算时间上界为O(n3)。

5518

被折叠的 条评论
为什么被折叠?



