目录
备忘录法:
使用备忘录法求解矩阵连乘问题,输出最少乘法次数。
输入
每组数据包括两行,第一行为数组长度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;
}