- 问题描述
-
给定一个有n个矩阵的矩阵链A1A2A3…An,其中矩阵Ai(i=1,2,3…n)的维度为pi-1*pi。我们知道,两个维度分别为m*r和r*n的矩阵用一般的矩阵乘法相乘,所需的运算次数为m*r*n,最后得到一个维度为m*n的结果矩阵。对于矩阵链问题,因为矩阵乘法具有结合律,其运算顺序有很多中选择。换句话说,不论如何括号其乘积,最后结果都会是一样的。例如,若有四个矩阵A、B、C和D,将可以有:
(ABC)D = (AB)(CD) = A(BCD) = A(BC)D = ...
但括号其乘积的顺序会影响到需要计算乘积所需简单算术运算的数目,即其效率。例如,设A为一10*30矩阵,B为30*5矩阵与C为5*60矩阵,则:
(AB)C有(10*30*5) + (10*5*60) = 1500 + 3000 = 4500 个运算 A(BC)有(30*5*60) + (10*30*60) = 9000 + 18000 = 27000 个运算 ...
明显地,第一种方式要有效多了。所以,矩阵链乘法问题也就是如何对矩阵乘积加括号,使得它们的乘法次数达到最少。
- 输入
-
输入的第一行为一个正整数n(1<=n<=200)。表示矩阵的个数。
输入的第二行包含n+1个整数,分别表示pi(0<=i<=n),其中每个pi在[1,200]范围内。 - 输出
-
输出一个整数表示最少要进行的乘法次数。
- 样例输入
-
3 1 2 3 4 3 10 30 5 60
- 样例输出
-
18 4500
属于动态规划题,其实也可以看做是一道贪心题,通过求出局部最优,从而得到全局最优,下面给出动态转移方程:
dp[i][j]:表示矩阵从i到j链乘需要的最小次数;s[i-1]为i矩阵的行数,s[i]为i矩阵的列数。如果i=j;dp[i][j]=0;否者dp[i][j]=max(dp[i][k]+dp[k+1][j]+s[i-1]*s[k]*s[j]);
AC代码:
#include<iostream> #include<string.h> #define N 205 using namespace std; int s[N]; int dp[N][N]; int slove(int n) { int i; for(i=1;i<=n;++i) dp[i][i]=0; for(int k=2;k<=n;++k) { for(int j=1;j<=n-k+1;++j) { i=j+k-1; dp[j][i]=999999999; for(int r=j;r<i;++r) dp[j][i]=min(dp[j][i],(dp[j][r]+dp[r+1][i]+s[j-1]*s[r]*s[i])); } } return dp[1][n]; } int main() { int n; while(cin>>n) { for(int i=0;i<=n;++i) cin>>s[i]; cout<<slove(n)<<endl; }return 0; }
http://cdn.ac.nbutoj.com/Problem/view.xhtml?id=1003&&矩阵链乘
最新推荐文章于 2022-11-25 19:12:32 发布