矩阵链的乘法问题【动态规划】

例:
P=<30,35,15,5,10,20> 它对应5个矩阵
A1:30×35 A2:35×15 A3:15×5 A4:5×10 A5:10×20

先计算:
m[1,1]=0 m[2,2]=0 m[3,3]=0 m[4,4]=0 m[5,5]=0

当r=2表示两个矩阵相乘的运算量:
m[1,2]=30×35×15=15750
m[2,3]=35×15×5=2625
m[3,4]=15×5×10=750
m[4,5]=5×10×20=1000

r=3表示3个矩阵相乘的运算量:

m[1,3]=min{m[1,2]+30×15×5,m[2,3]+30×35×5}=min{15750+2625,2625+5250}=7875 A1(A2A3) s[1,3]=1
m[2,4]=min{m[2,3]+35×5×10,m[3,4]+35×15×10}={2625+1750,750+5250}=4375 (A2A3)A4 s[2,4]=3
m[3,5]=min{m[3,4]+15×10×20,m[4,5]+15×5×20}=2500 A3(A4A5) s[3,5]=3

r=4表示4个矩阵相乘的运算量:
m[1,4]=min{m[2,4]+30×35×10,m[1,2]+m[3,4]+30×15×10,m[1,3]+30×5×10}
=min{4375+10500,15750+750+4500,7875+1500}
=9375 [A1A2A3]A4---->(A1(A2A3))A4 s[1,4]=3
m[2,5]=min{m[3,5]+35×15×20,m[2,3]+m[4,5]+35×5×20,m[2,4]+35×10×20}
=min{2500+10500,2625+1000+3500,4375+7000}
=7125 (A2A3)(A4A5) s[2,5]=3

r=5表示5个矩阵相乘的运算量:
m[1,5]=min{m[2,5]+30×35×20,m[1,2]+m[3,5]+30×15×20,m[1,3]+m[4,5]+30×5×20,m[1,4]+30×10×20}
=min{7125+21000,15750+2500+9000,7875+1000+3000,9375+9000}
=11875 (A1A2A3)(A4A5)---->(A1(A2A3))(A4A5) s[1,5]=3

优化函数备忘录:
r=1 m[1,1]=0 m[2,2]=0 m[3,3]=0 m[4,4]=0 m[5,5]=0
r=2 m[1,2]=15750 m[2,3]=2625 m[3,4]=750 m[4,5]=1000
r=3 m[1,3]=7875 m[2,4]=4375 m[3,5]=2500
r=4 m[1,4]=9375 m[2,5]=7125
r=5 m[1,5]=11875

标记函数:
r=2 s[1,2]=1 s[2,3]=2 s[3,4]=3 s[4,5]=4
r=3 s[1,3]=1 s[2,4]=3 s[3,5]=3
r=4 s[1,4]=3 s[2,5]=3
r=5 s[1,5]=3

根据 s[1,5]=3 推出最后一次划分的位置为3 [A1A2A3][A4A5] 然后再由[A1A2A3]找s[1,3]=1 推出最后一次划分位置为1 A1(A2A3)
所以最终答案为:(A1(A2A3))(A4A5) 运算次数为:11875次

#include<iostream>
#include<iomanip>
using namespace std;
int s[50][50],m[50][50];
int a[100];		  

void juzhen(int n)//通过迭代实现动态规划
{
	int i,r,j,t,k;
	for(i=1;i<=n;i++)
		for(j=i;j<=n;j++)  //将m[i,i]与s[i,j]赋初值
		{
			m[i][i]=0;
			s[i][j]=i;
		}
	for(r=2;r<=n;r++)  //r为当前计算的链长
		for(i=1;i<=n-r+1;i++) //n-r+1为当前最后一个r链的前边界
		{
			j=i+r-1;    //计算前边界为i,后边界为j的链r
			m[i][j]=m[i+1][j]+a[i-1]*a[i]*a[j]; //划分为Ai(Ai+1 ... Aj)
			s[i][j]=i;  //记录分割位置
			for(k=i+1;k<=j-1;k++)
			{
				t=m[i][k]+m[k+1][j]+a[i-1]*a[k]*a[j]; //划分位置为(Ai ... Ak)(Ak+1 ... Aj)
				if(t<m[i][j])  //用更好的值替换
				{
					m[i][j]=t;
					s[i][j]=k;
				}
			}
		}
}
void youhua(int n) //表格输出优化函数值备忘录
{
	int r,i,j;
	cout<<"r=1"<<"    ";
	for(i=1;i<=n;i++)
		cout<<"m["<<i<<","<<i<<"]"<<"="<<left<<setw(6)<<m[i][i]<<"    ";
	cout<<endl;
	for(r=2;r<=n;r++)
	{
		cout<<"r="<<r<<"    ";
		for(i=1;i<=n-r+1;i++)
		{
			j=i+r-1; //记录位置
			cout<<"m["<<i<<","<<j<<"]"<<"="<<left<<setw(6)<<m[i][j]<<"    ";		
		}
		cout<<endl;
	}
}
void biaoji(int n) //表格输出标记函数
{
	int r,i,j;
	for(r=2;r<=n;r++)
	{
		cout<<"r="<<r<<"    ";
		for(i=1;i<=n-r+1;i++)
		{
			j=i+r-1; //记录位置
			cout<<"s["<<i<<","<<j<<"]"<<"="<<left<<setw(6)<<s[i][j]<<"    ";
		}
		cout<<endl;
	}
}
void kuohao1(int i,int j)// 递归输出括号表示法
{
	if(i==j)
		cout<<"A"<<i;
	else if(i+1==j)
		cout<<"(A"<<i<<"A"<<j<<")";
	else
	{
		cout<<"(";
		kuohao1(i,s[i][j]); //取s[i,j]做分割位置进行递归
		kuohao1(s[i][j]+1,j);
		cout<<")";
	}
}
void kuohao2(int n) //表格输出
{
	int i,j,r;
	for(r=2;r<=n;r++)
	{
		cout<<"r="<<r<<"  ";
		for(i=1;i<=n-r+1;i++)
		{
			j=i+r-1;
			kuohao1(i,j); 
			cout<<"    ";
		}
		cout<<endl;
	}
}
//主函数
void main()
{
	int n,i;
	cout<<"请输入矩阵个数:";cin>>n;
		cout<<"请输入对应矩阵:";
	for (i=0;i<=n;i++)
		cin>>a[i];
	for (i=0;i<n;i++)
		cout<<"A"<<i+1<<":"<<a[i]<<"*"<<a[i+1]<<"  ";
	cout<<endl;
	juzhen(n);
	cout<<"优化函数值的备忘录:"<<endl;youhua(n);
	cout<<"标记函数:"<<endl;biaoji(n);
	cout<<"括号表示法:"<<endl;kuohao2(n);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值