算法设计与分析 8.1 矩阵连乘问题

本文讨论了如何在给定矩阵中寻找从1到n的全局最优分割点,通过递归函数cou()实现局部最优,然后非递归地优化计算过程。同时分析了两种方法的时间复杂度(O(n^3))和空间复杂度(O(n^2))。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如何从com[][]com[][]com[][]中找到全局最优解?
在这里插入图片描述

	int cou(int i,int j)
	{
		if(temp[i][j]>=0)
		{
			return temp[i][j];
		}
		if(i==j)
		{
			temp[i][j]=0;
	        com[i][j]=0; 
			return temp[i][j];
		}
		if(i+1==j)
		{
			temp[i][j]=r[i]*r[i+1]*r[i+2];
			com[i][j]=i;
			return  temp[i][j];
		} 
		int x=cou(i,i)+cou(i+1,j)+r[i]*r[i+1]*r[j+1];
		com[i][j]=i;
		int y;
		for(int k=i+1;k<j;k++)
		{
			y=cou(i,k)+cou(k+1,j)+r[i]*r[k+1]*r[j+1];
			
			if(y<x)
			{
				x=y;
				com[i][j]=k;
			}
		}
		temp[i][j]=x;
		return temp[i][j];
	} 

上述代码为求解i到j的局部最优分割点的函数

本题的全局最优解找法:找到1到n间的首个最优分割点k。而后递归的运行函数cou(1,k)和cou(k+1,n);每次运行都将得到的局部最优分割点kik_{i}ki​加入记录全局最优解的集合best[]中。
完整代码

#include<iostream>
using namespace std;
 
int n=4;
int r[100]={0,5,20,50,1,100};//保存矩阵大小 
int com[100][100]={0};//保存矩阵编号 
int temp[100][100];//保存Mij最优计算量 
 
int cou(int i,int j)
{
	cout<<i<<"->"<<j<<endl;
	if(temp[i][j]>=0)//已经计算过 
	{
		//因为是从小到大,所以没有覆盖 
		return temp[i][j];
	}
	
	if(i==j)//此时 Mii 也就是同一个矩阵 
	{
		temp[i][j]=0;//所需计算量为0 		
//		com[i][j]=0;//此时分割点,已经在初始化时赋值了 
		return temp[i][j];
	}
	if(i+1==j)//两个矩阵相乘 结果固定 
	{
		temp[i][j]=r[i]*r[i+1]*r[i+2];
		com[i][j]=i;//此时分割点的下标 是i
		return  temp[i][j];
	} 
	//其他情况 此时有多个情况
	
	//其中一个选择,作为基准值 
	int x=cou(i,i)+cou(i+1,j)+r[i]*r[i+1]*r[j+1];//0增益+已知增益+新增增益
	com[i][j]=i;//记录这种分割点
	int y;
	for(int k=i+1;k<j;k++)
	{
		y=cou(i,k)+cou(k+1,j)+r[i]*r[k+1]*r[j+1];//记录每种选择下的增益
		
		if(y<x)//当前值更优化 
		{
			x=y;
			com[i][j]=k;//分割点在k+1 
		}
	}
	temp[i][j]=x;//
	return temp[i][j];
} 
 
void show(int i,int j)
{
	if(i==j)
	{
		if(i==1)cout<<"M"<<i;
		else cout<<"M"<<i;
		return ;
	}
	cout<<"(";
	show(i,com[i][j]);
	cout<<"*";
	show(com[i][j]+1,j);
	cout<<")";
	
}
int main()
{
	//初始化 
	for(int i=0;i<=n;i++)
	{
		for(int j=0;j<=n;j++)
		{
			temp[i][j]=-1;
			com[i][j]=0;
		}
	}
	//调用
	cou(1,n);
	
	for(int i=1;i<=n;i++)
	{
		cout<<endl;
		for(int j=1;j<=n;j++)
		{
			cout<<i<<""<<j<<":"<<com[i][j]<<"\t";
		}
	}
	cout<<endl;
 
	//输出结果 递归 
	int x=1,y=n;
	cout<<"次数:"<<temp[x][y]<<endl;
	cout<<"计算顺序:";
	show(x,y);
	 
}

2.本题的计算模型及非递归算法的时间复杂度?

计算模型:

mi,j=m_{i,j}=mi,j=000 (i=j)(i=j)(i=j)

mi,j=ri∗ri+1∗ri+2m_{i,j}=r_{i}*r_{i+1}*r_{i+2}mi,j=riri+1ri+2 (j=i+1)(j=i+1)(j=i+1)

mi,j=min(mi,k+mk+1,j+ri∗rk+1∗rj+1)m_{i,j}=min(m_{i,k}+m_{k+1,j}+r_{i}*r_{k+1}*r_{j+1})mi,j=min(mi,k+mk+1,j+rirk+1rj+1) (i<=k<j,i<j)(i<=k<j,i<j)(i<=k<j,i<j)

用用com[][]存储使得mi,j为最小值时的k值存储使得m_{i,j}为最小值时的k值存储使得mi,j为最小值时的k

非递归代码:

	void fei()
	{
		int n=4;
		int r[10]={0,5,20,50,1,100};
	 
		int com[10][10]={0};
		int m[10][10]={0};
		for(int i=1;i<=n;i++)
		{
			m[i][i]=0;
			m[i][i+1]=r[i]*r[i+1]*r[i+2];
			com[i][i+1]=i;
		}
		for(int j=1;j<=n;j++)
		{
			for(int i=2;i<=n;i++)
			{
				if(i+j-1>n)continue; 
				m[j][j+i-1]=m[j][j]+m[j+1][j+i-1]+r[j]*r[j+1]*r[j+i];
				com[j][j+i-1]=i; 
				int temp; 
				for(int k=j+1;k<=j+i-1;k++) 
				{
					temp=m[j][k]+m[k+1][j+i-1]+r[j]*r[k+1]*r[j+i];
					if(temp<m[j][j+i-1])
					{
						m[j][j+i-1]=temp;
						com[j][j+i-1]=k;
					}
				} 
			}
		} 
		cout<<endl<<endl<<m[1][n];
		for (int i=1;i<=n;i++) 
		{ 
			cout<<endl; 
			for (int j=1;j<=n;j++) 
				cout<<com[i][j];
		}
		show(1,n); 
	} 
	void fun()
	{
		int n=4;
		int r[10]={0,5,20,50,1,100};
		int com[10][10]={0};
		int m[10][10]={0};
		for(int i=1;i<n;i++)
		{
			m[i][i]=0;
			m[i][i+1]=r[i]*r[i+1]*r[i+2];
			com[i][i+1]=i+1;
		}
		for(int s=2;s<n;s++)
		{
			for(int i=1;i+s<n+1;i++)
			{
				int j=i+s;
				m[i][j]=m[i][i]+m[i+1][j]+r[i]*r[i+1]*r[j+1];
				com[i][j] = i;
				for (int k=i+1;k<j;k++)
				{
					int t=m[i][k]+m[k+1][j]+ r[i]*r[k+1]*r[j+1];
					if (t <m[i][j])
					{ 
						m[i][j] = t; 
						com[i][j]= k;
					}
				}
			} 
		}
		cout<<endl<<endl<<m[1][n];
		for (int i=1;i<=n;i++) 
		{ 
			cout<<endl; 
			for (int j=1;j<=n;j++) 
				cout<<com[i][j];
		}
		show(1,n);
	} 

时间复杂度:

函数fei():外层循环n层,内层循环n2层外层循环n层,内层循环n^2层外层循环n层,内层循环n2 O(n)=n3O(n)=n^3O(n)=n3

同样,函数fun():外层循环n层,内层循环n2层外层循环n层,内层循环n^2层外层循环n层,内层循环n2 O(n)=n3O(n)=n^3O(n)=n3

T(n)=O(n3)T(n)=O(n^3)T(n)=O(n3)

空间复杂度:

都使用了二维数组 T(n)=O(n2)T(n)=O(n^2)T(n)=O(n2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值