动态规划 矩阵链相乘

1. 问题

设S1,A2,A3,…An为n个矩阵的序列,其中Ai为Pi-1×Pi阶矩阵,这个矩阵链的输入用向量P=<P0,P1…Pn>给出。
给定向量P,确定一种乘法次序,使得基本运算的总次数达到最小。

2. 解析

我才用的矩阵为
A1(30×35)、
A2(35×15)、
A3(15×5)、
A4(5×10)、
A5(10×20)、
A6(20×25),
那么得到的P=<30,35,15,5,10,20,25>

设m[i,j]为计算机矩阵Ai…j所需的标量乘法运算次数的最小值,对此计算A1…n的最小代价就是m[1,n]。现在需要来递归定义m[i,j],分两种情况进行讨论如下:

1)当i==j时:m[i,j] = 0,(此时只包含一个矩阵)
2)当i<j 时:从步骤1中需要寻找一个k(i≤k<j)值,使得m[i,j] =min{m[i,k]+m[k+1,j]+pi-1pkpj} (i≤k<j)
设矩阵Ai的维数为pi-1pi,i=1,2…n。输入序列为:p=<p0,p1,…pn>,length[p] = n+1。使用m[n][n]保存m[i,j]的代价,s[n][n]保存计算m[i,j]时取得最优代价处k的值,最后可以用s中的记录构造一个最优解。
实现过程定义两个二维数组m和s,为了方便计算其第一行和第一列都忽略,行标和列标都是1开始

3. 设计

#include <iostream>
using namespace std;

#define N 6
#define MAXVALUE 1000000

void matrix_chain_order(int* p, int len, int m[N + 1][N + 1], int s[N + 1][N + 1]);
void print_optimal_parents(int s[N + 1][N + 1], int i, int j);

int main()
{
	int p[N + 1] = { 30,35,15,5,10,20,25 };
	int m[N + 1][N + 1] = { 0 };
	int s[N + 1][N + 1] = { 0 };
	int i, j;
	matrix_chain_order(p, N + 1, m, s);
	cout << "最佳次序为:" << endl;
	print_optimal_parents(s, 1, N);
	cout << endl;
	return 0;
}

void matrix_chain_order(int* p, int len, int m[N + 1][N + 1], int s[N + 1][N + 1])
{
	int i, j, k, t;
	for (i = 0; i <= N; ++i)
		m[i][i] = 0;
	for (t = 2; t <= N; t++)  //当前链乘矩阵的长度
	{
		for (i = 1; i <= N - t + 1; i++)  //从第一矩阵开始算起,计算长度为t的最少代价
		{
			j = i + t - 1;//长度为t时候的最后一个元素
			m[i][j] = MAXVALUE;  //初始化为最大代价
			for (k = i; k <= j - 1; k++)   //寻找最优的k值,使得分成两部分k在i与j-1之间
			{
				int temp = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
				if (temp < m[i][j])
				{
					m[i][j] = temp;   //记录下当前的最小代价
					s[i][j] = k;      //记录当前的括号位置,即矩阵的编号
				}
			}
		}
	}
}

//s中存放着括号当前的位置
void print_optimal_parents(int s[N + 1][N + 1], int i, int j)
{
	if (i == j)
		cout << "A" << i;
	else
	{
		cout << "(";
		print_optimal_parents(s, i, s[i][j]);
		print_optimal_parents(s, s[i][j] + 1, j);
		cout << ")";
	}

}

4. 分析

matrix_chain_order函数具有循环嵌套,深度为3层,运行时间为O(n3)。
如果采用递归进行实现,则需要指数级时间Ω(2n),因为中间有些重复计算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值