矩阵最少乘法
题意:
给你2个矩阵A、B,我们使用标准的矩阵相乘定义C=AB如下:
A阵列中栏(column)的数目一定要等于B阵列中列(row)的数目才可以做此2阵列的相乘。若我们以rows(A),columns(A)分别代表A阵列中列及栏的数目,要计算C阵列共需要的乘法的数目为:rows(A)*columns(B)*columns(A)。例如:A阵列是一个10x20的矩阵,B阵列是个20x15的矩阵,那么要算出C阵列需要做10*15*20,也就是3000次乘法。
要计算超过2个以上的矩阵相乘就得决定要用怎样的顺序来做。例如:X、Y、Z都是矩阵,要计算XYZ的话可以有2种选择:(XY)Z 或者X(YZ)。假设X是5x10的阵列,Y是10x20的阵列,Z是20x35的阵列,那个不同的运算顺序所需的乘法数会有不同:
(XY)Z
- 5*20*10 = 1000次乘法完成(XY),并得到一5x20的阵列。
- 5*35*20 = 3500次乘法得到最后的结果。
- 总共需要的乘法的次数:1000+3500=4500。
X(YZ)
- 10*35*20 = 7000次乘法完成(YZ),并得到一10x35的阵列。
- 5*35*10 = 1750次乘法得到最后的结果。
- 总共需要的乘法的次数:7000+1750=8750。
很明显的,我们可以知道计算(XY)Z会使用较少次的乘法。
这个问题是:给你一些矩阵,你要写一个程式来决定该如何相乘的顺序,使得用到乘法的次数会最少。
思路:最优矩阵链乘问题,典型的动态规划题目。
#include<stdio.h>
#define m 1000
#define inf 0x3f3f3f3f
int dp[m][m],s[m][m],p[m],n;
void print(int i,int j)//递归输出所有的结果
{
if(i==j)
printf("A%d",i); //输出是第几个数据
else
{
printf("(");
print(i,s[i][j]);//递归下一个数据
printf(" x ");
print(s[i][j]+1,j);
printf(")");
}
}
void work()
{
int i,j,k,l,t;
for(i=1; i<=n; i++)
dp[i][i]=0;//首先初始化为0
for(l=2; l<=n; l++)
for(i=1; i<=n-l+1; i++)
{
j=i+l-1; //判断i和j之间的最优解
dp[i][j]=inf;
for(k=i; k<=j-1; k++)
{
t=dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j];
if(t<dp[i][j])
{
dp[i][j]=t; //保持最优解
s[i][j]=k; //记录需要加括号的地方
}
}
}
print(1,n); //输出i和j之间的最优解
puts("");
}
int main()
{
int c=1,i;
while(scanf("%d",&n)&&n)
{
for(i=1; i<=n; i++)
scanf("%d%d",&p[i-1],&p[i]);//输入数据
printf("Case %d: ",c++);
work();
}
return 0;
}