实验报告 动态规划 矩阵连乘问题

一.题目描述

输入:n个矩阵A1,A2,…,An,其中Ai的维数为pi-1×pi
Ai 和Ai+1是可乘的

输出:连乘积A1A2A3…An

优化目标:最小计算代价(最优的计算次序)

二.思路描述

1.输入分析

n个矩阵,输入他们的阶数,因为矩阵可以连乘,所以相邻矩阵的行数和列数相同,输入的时候相邻矩阵的行数和阶数只需要输入一个。

举例说明:

比如有三个矩阵A1(2*3)  A2(3*4)   A3(4*3),它们是可以连乘的,此时输入只需要输入 2 3 4 3即可;

2.输出分析

解决了输入的问题,接下来考虑算法的输出问题,题目要求输出最小计算代价,那么我们首先要考虑的问题就是什么叫做最小计算代价,这里我举例说明。

依旧以这三个数组为例:

A1(2*3)  A2(3*4)   A3(4*3)

根据矩阵的乘法可以知道,矩阵和矩阵相乘,实际上是矩阵里面的数字相乘,

并且A1*A2*A3=(A1*A2)*A3=A1*(A2*A3)

可以发现矩阵的乘法运算满足结合律,那么我们可以明白:

不同的计算代价对应于不同的结合律

这里我们直接计算说明

(A1*A2)*A3

它的计算次数为

2*3*4+2*4*3=48次;

A1*(A2*A3)

它的计算次数为

3*4*3+2*3*3=54次

很显然48 为该矩阵连乘的最小次数;

3.核心算法分析

我们进一步推广,有一串可以连乘的矩阵;

A1 A2 A3 A4...........An;

则对应的边有数组C1 C2 C3 C4 C5 ......Cn+1

为了方便表达,我们设B[i,j]为从矩阵A[i]到A[j]连乘所需要的次数;

进而我们通过构建可以得出动态规划的循环式

B[i,j]=B[i,k]+B[k+1,j]+C[i]*C[k]*C[j];

我们可以通过循环,来不断的确定所有的B[i,j]的值,进而求得最优值;

4.形象演示

我们通过表格的形式详细讲解动态规划的过程.

我们假设表格代表B[i,j];

1. 初始化

显然我们可知

i<=j

所以下半部分永远为0;

且当i=j时,B[i,j]=0;

红色代表未确定,绿色代表以确定,蓝色代表正在确定中。

0

0

0000
000000
000000
000000
000000
000000

那么我们依照算法

B[i,j]=B[i,k]+B[k+1,j]+C[i]*C[k]*C[j];、

可以发现,我们可以向右上方向逐层递进,最后得出结果;

这里我们可以计算蓝色区域的结果,最后一次循序渐进;

0

x1

0000
00x2000
000x300
0000x40
00000x5
000000

4.循环附加条件

举例说明

B[i,j]可能有多种计算方法导致不同的计算结果,用动态规划的方法,当出现新的B[i,j]时,我们需要进行比较并及时更新。

三.源代码

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin>>n;
	int A[n-1][n-1];//代表从第i个矩阵到第j个矩阵所需要的计算次数,
	

	int code[n];//矩阵依次的行列数
	for(int i=0;i<n;i++)
	{
		cin>>code[i];//输入所有矩阵的行和列,相邻的只需要写一个
	}
	for(int i=0;i<n-1;i++)
	{
		for(int j=0;j<n-1;j++)
		{
			A[i][j]=0;
		}
	}
	for(int r=0;r<n-1;r++)//注意循环的顺序,循序渐进 i为两个矩阵之间相差的矩阵数量
	{
		for(int i=0;i<n-2;i++)
		{
			int j=i+r+1;
			if(A[i][j]==0)
			{
				A[i][j]=A[i][i]+A[i+1][j]+code[i]*code[i+1]*code[j+1];//,前后的矩阵所需要的计算次数,以及连接这两个大型矩阵所需要的次数
							//说明从第i个矩阵到第j个矩阵所断开的地方
			}
			for(int k=i;k<=j;k++)
			{
				int min=A[i][k]+A[k+1][j]+code[i]*code[k+1]*code[j+1];
				if(min<A[i][j])
				{
					A[i][j]=min;
				}
			}
		}
		
	}
	cout<<A[0][n-2];
	
	return 0;
}

四 .测试数据

五.遇到的问题及解决方法

动态规划的实现主要需要避免数据溢出的情况出现,因此要巧妙设计循环步骤。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值