一个n*m的矩阵由n行m列共n*m排列而成。两个矩阵A和B可以相乘当且仅当A的列数等于B的行数。一个n*m的矩阵乘m*p的矩阵,运算量为n*m*p。
矩阵乘法不满足分配律,但满足结合律。因此A*B*C既可以按顺序(A*B)C也可以按A(B*C)来进行。假设A、B、C分别是2*3、3*4、4*5的,则(A*B)C运算量是2*3*4+2*4*5=64,A(B*C)的运算量是3*4*5*2*3*5=90.显然第一种顺序节省运算量。
给出n个矩阵组成的序列,设计一种方法把他们依次乘起来,使得总的运算量尽量小。假设第i个矩阵A[i]是P[i-1]*P[i]的。
1.递归方式:自顶向下
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
#include <cmath>
using namespace std;
#define INF 1 << 30
struct Matrix{
int l, r;
}M[100];
int d[100][100];
int dp(int l, int r)
{
if(l == r)
return 0;
if(d[l][r])return d[l][r];
d[l][r] = INF;
for(int i = l; i < r; i++)
{
d[l][r] = min(d[l][r], dp(l, i) + dp(i+1, r) + M[l].l * M[i].r * M[r].r);
}
return d[l][r];
}
int main()
{
// freopen("in.txt", "r", stdin);
int n;
while(cin >> n && n)
{
memset(d, 0, sizeof(d));
for(int i = 0; i < n; i++)
cin >> M[i].l >> M[i].r;
d[0][n] = dp(0, n-1);
cout << d[0][n] << endl;
}
}
2.递推方式,自底向上
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<iostream>
#define INF 1 << 30
using namespace std;
struct Matrix{
int x, y;
}M[105];
int dp[105][105];
int main()
{
// freopen("in.txt", "r", stdin);
int n;
while(cin >> n && n)
{
for(int i = 1; i <= n; i++)
{
cin >> M[i].x >> M[i].y;
dp[i][i] = 0;
}
for(int i = 1; i <= n-1; i++)
for(int j = 1; j < n && j + i <= n; j++)
{
dp[j][j+i] = INF;
for(int k = j; k < j+i; k++)
{
dp[j][j+i] = min(dp[j][j+i], dp[j][k] + dp[k+1][j+i] + M[j].x * M[k].y * M[j+i].y);
}
}
cout << dp[1][n] << endl;
}
return 0;
}