动态规划法解矩阵连乘问题样本
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
动态规划法解矩阵连乘问题
实验内容
给定n个矩阵{A1,A2,….An},其中Ai与Ai+1是可乘,i=1,2,3。。。,n-1。咱们要计算这n个矩阵连乘积。由于矩阵乘法满足结合性,故计算矩阵连乘积可以有许多不同计算顺序。这种计算顺序可以用加括号方式拟定。若一种矩阵连乘积计算顺序完全拟定,也就是说该连乘积已完全加括号,则咱们可依此顺序重复调用2个矩阵相乘原则算法计算出矩阵连乘积。解题思路
将矩阵连乘积A(i)A(i+1)…A(j)简记为A[i:j],这里 i <= j。考察计算A[i:j]最优计算
顺序。设这个计算顺序在矩阵A(k)和A(k+1)之间将矩阵链断开,i <= k < j,则其相应完全加括号方式为(A(i)A(i+1)…A(k)) * (A(k+1)A(k+2)…A(j))。
特性:计算A[i:j]最优顺序所包括计算矩阵子链 A[i:k]和A[k+1:j]顺序也是最优。
矩阵连乘计算顺序问题最优解包括着其子问题最优解。
设计算A[i:j],1 <= i <= j <= n,所需要至少数乘次数m[i,j],则原问题最优值为m[1,n] 当i = j时,A[i:j]=Ai,因而,m[i,i] = 0,i = 1,2,…,n
当i < j时,m[i,j] = m[i,k] + m[k+1,j] + p(i-1)p(k)p(j)这里A(i)维数为p(i-1)*(i)(注:p(i-1)为矩阵A(i)行数,p(i)为矩阵A[i]列数)
实验
实验代码
#include
#include
using namespace std ;
class matrix_chain
{
public:
matrix_chain(const vector
cols = c ;
count = cols.size () ;
mc.resize (count) ;
s.resize (count) ;
for (int i = 0;i < count;++i) {
mc[i].resize (count) ;
s[i].resize (count) ;
}
for (i = 0;i < count;++i) {
for (int j = 0;j < count;++j) {
mc[i][j] = 0 ;
s[i][j] = 0 ;
}
}
}
// 记录每次子问题成果
void lookup_chain () {
__lookup_chain (1,count - 1) ;
min_count = mc[1][count - 1] ;
cout << "min_multi_count = "<< min_count << endl ;
// 输出最优计算顺序
__trackback (1,count - 1) ;
}
// 使用普通办法进行计算
void calculate () {
int n = count - 1;// 矩阵个数
// r 表达每次宽度
// i,j表达从从矩阵i到矩阵j
// k 表达切割位置
for (int r = 2;r <= n;++ r) {
for (int i = 1;i <= n - r + 1;++ i) {
int j = i + r - 1 ;
// 从矩阵i到矩阵j连乘,从i位置切割,前半某些为0
mc[i][j] = mc[i+1][j] + cols[i-1] * cols[i] * cols[j] ;
s[i][j] = i ;
for (int k = i + 1;k < j;++ k) {
int temp = mc[i][k] + mc[k + 1][j] +
cols[i-1] * cols[k] * cols[j] ;
if (temp < mc[i][j]) {
mc[i][j] = temp ;
s[i][j] = k ;
}
} // for k
} // for i
} // for r
min_count = mc[1][n] ;
cout << "min_multi_count = "<< min_count << endl ;
// 输出最优计算顺序
__trackback (1,n) ;
}
private:
int __lookup_chain (int i,int j) {
// 该最优解已求出,直接返回
if (mc[i][j] > 0) {
return mc[i][j] ;
}
if (i == j) {
return 0 ;// 不需要计算,直接返回
}
// 下面两行计算从i到j按照顺序计算状况
int u = __lookup_chain (i,i) + __lookup_chain (i + 1,j)
+ cols[i-1] * cols[i] * cols[j] ;
s[i][j] = i ;
for (int k = i + 1;k < j;++ k) {
int temp = __lookup_chain(i,k) + __lookup_chain(k + 1,j)
+ cols[i - 1] * cols[k] * cols[j] ;
if (temp < u) {
u = temp ;
s[i][j] = k ;
}
}
mc[i][j] = u ;