问题描述:
给定n个矩阵A1,A2,…,An,其中,Ai与Aj+1是可乘的,i=1,2,…,n-l。
你的任务是要确定矩阵连乘的运算次序,使计算这n个矩阵的连乘积A1A2…An时总的元素乘法次数达到最少。
例如:3个矩阵A1,A2,A3,阶分别为10×100、100×5、5×50,计算连乘积A1A2A3时按(A1A2)A3所需的元素乘法次数达到最少,为7500次。
输入
测试数据有若干组,每组测试数据有2行。
每组测试数据的第1行是一个整数n,(0<n<20),第2行是n+1个正整数p0、p1、p2、…、pn,这些整数不超过100,相邻两个整数之间空一格,他们表示n个矩阵A1,A2,…,An,的阶pi-1´pi,i=1,2,…,n。
输入直到文件结束。
输出
对输入中的每组测试数据,输出2行。先在一行上输出“Case #”,其中“#”是测试数据的组号(从1开始),再在第2行上输出计算这n个矩阵的连乘积A1A2…An时最少的总的元素乘法次数,再空一格,接着在同一行上输出矩阵连乘的添括号形式。
注意:最外层括号应去掉。
实验结果:
输入样例
3
10 100 5 50
4
50 10 40 30 5
输出样例
Case 1
7500 (A1A2)A3
Case 2
10500 A1(A2(A3A4))
程序代码如下:
#include<iostream>
#include <fstream>
#include <cassert>
#include <string>
#include <sstream>
using namespace std;
const int N=100;
int m[N][N],s[N][N];
void PrintAnswer(int i,int j)
{
if(i==j)
cout<<"A"<<i;
else
{
cout<<"(";
PrintAnswer(i,s[i][j]);
PrintAnswer(s[i][j]+1,j);
cout<<")";
}
}
void Matrix_Multi(int *p,int length)
{
int n=length-1;
int l,i,j,k,q=0;
//m[i][i]只有一个矩阵,相乘次数为零,所以m[i][i]=0
for(i=1;i<length;i++)
{
m[i][j]=0;
}
for(l=2;l<=n;l++) //宽度从2到n
{
for(i=1;i<=n-l+1;i++)
{
j=i+l-1; //以i为起始位,j为末位,长度为l
m[i][j]=0x7fffffff;
for(k=i;k<=j-1;k++)
{
q=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
if(q<m[i][j])
{
m[i][j]=q;
s[i][j]=k;
}
}
}
}
}
void readTxt(string file)
{
ifstream infile;
infile.open(file.data());
assert(infile.is_open());
string s;
int i=1;
while(getline(infile,s))
{
int a=atoi(s.c_str());
getline(infile,s);
istringstream tmp(s);
int x[a+1];
for(int i=0;i<=a;i++)
{
tmp>>s;
x[i]=atoi(s.c_str());
}
Matrix_Multi(x,a+1);
cout<<"Case "<<i<<endl;
i++;
cout<<m[1][a]<<" ";
PrintAnswer(1,a);
cout<<endl;
}
infile.close();
}
int main()
{
readTxt("input.txt");
return 0;
}
运行结果:
![c22d8106872eec4c0b9af3be7874ae4c.png](https://img-blog.csdnimg.cn/img_convert/c22d8106872eec4c0b9af3be7874ae4c.png)
思路详解:
https://blog.csdn.net/qq_32919451/article/details/80643118blog.csdn.net