0
点赞
收藏
分享

微信扫一扫

HNUCM 矩阵连乘问题合集

googlefrank 2022-05-02 阅读 75

目录

 备忘录法:

动态规划法: 

构造最优解 


 

 备忘录法:

使用备忘录法求解矩阵连乘问题,输出最少乘法次数。

输入

每组数据包括两行,第一行为数组长度n,第二行为存储矩阵维数的一维数组。

输出

矩阵连乘最优计算次数。

样例输入 Copy

7
30 35 15 5 10 20 25

样例输出 Copy

15125

 

 

 

 

#include<bits/stdc++.h>
using namespace std;
int m[1005][1005];
int p[1005];


int  lookupChain(int i,int j){
	if(m[i][j]>0)return m[i][j];
	if(i==j)return 0;
	int u=lookupChain(i+1,j)+p[i-1]*p[i]*p[j];
	for(int k=i+1;k<j;k++){
		int t=lookupChain(i,k)+lookupChain(k+1,j)+p[i-1]*p[k]*p[j];
		if(t<u)u=t;
	}
	m[i][j]=u;
	return u;
}
int main(){
	int n;
	
	while(cin>>n){
		memset(p,0,1005);
		memset(m,0,sizeof(m));
		for(int i=1;i<=n;i++)cin>>p[i];
		cout<<lookupChain(2,n)<<endl;//从二开始
	}	
	return 0;
} 

动态规划法: 

使用动态规划算法求解矩阵连乘问题,输出最少乘法次数。

输入

每组数据包括两行,第一行为数组长度n,第二行为存储矩阵维数的一维数组。

输出

矩阵连乘最优计算次数。

样例输入 Copy

7
30 35 15 5 10 20 25

样例输出 Copy

15125
#include<bits/stdc++.h>
using namespace std;
int m[1005][1005];
int p[1005];

int main(){
	int n;
	
	while(cin>>n){
		memset(p,0,1005);
		memset(m,0,sizeof(m));
		for(int i=0;i<n;i++){//这里与上一个代码的区别,这里是从0开始的,因为不从0开始就无法得到m[1][6]
			cin>>p[i];
			m[i][i]=0;
		}
		m[n][n]=0;//上面只能初始化到n-1
		for(int r=2;r<=n;r++){
			for(int i=1;i<=n-r+1;i++){
				int j=r+i-1;
				m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];
				for(int k=i+1;k<j;k++){
					int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
					if(t<m[i][j])m[i][j]=t;
				}
			}
			
		}
		cout<<m[1][n-1]<<endl;
	}	
	return 0;
} 

构造最优解 

题目描述

使用动态规划算法求解矩阵连乘问题。

输入

每组数据包括两行,第一行为数组长度n,第二行为存储矩阵维数的一维数组。

输出

矩阵连乘最优计算次序。

样例输入 Copy

7
30 35 15 5 10 20 25

样例输出 Copy

A[2:2] * A[3:3]
A[1:1] * A[2:3]
A[4:4] * A[5:5]
A[4:5] * A[6:6]
A[1:3] * A[4:6]

 

 

 

#include<bits/stdc++.h>
using namespace std;
int m[1005][1005];//定义矩阵i到j的最小乘法次数
int p[1005];//定义矩阵维数
int n;
int s[1005][1005];//定义i与j之间的最优分割点
void zy(){//因为这里我定义的是全局变量所以不用传参数
	for(int r=2;r<=n;r++){//从2 开始,下面有解释
			for(int i=1;i<=n-r+1;i++){//这里注意i的范围
				int j=r+i-1;//规律观察得到j
				m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];
				s[i][j]=i;//相当于初始化最优分割点
				for(int k=i+1;k<j;k++){
					int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
					if(t<m[i][j]){ 
					m[i][j]=t;
					s[i][j]=k; //更新最优分割点
					} 
				}
			}			
		}
}

void huisu(int s[1005][1005],int i,int j)
{
    if(i==j)return;
    huisu(s,i,s[i][j]);
    huisu(s,s[i][j]+1,j);
    cout<<"A["<<i<<":"<<s[i][j]<<"] * A["<<s[i][j]+1<<":"<<j<<"]"<<endl;    
}

int main(){
	

	while(cin>>n){
		memset(p,0,1005);
		memset(m,0,sizeof(m));
		for(int i=0;i<n;i++){
			cin>>p[i];
			m[i][i]=0;//在这里已经初始化了r为1时的情况
		}
		m[n][n]=0;
		zy();
		huisu(s,1,n-1);
		//cout<<s[2][5]<<endl;
	}	
	return 0;
} 

 

举报

相关推荐

0 条评论