给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。例如,给定三个连乘矩阵{A1,A2,A3}的维数分别是10 * 100,100 * 5和5 * 50,采用(A1A2)A3,乘法次数为10 * 100 * 5 + 10 * 5 * 50=7500次,而采用A1(A2A3),乘法次数为100550+1010050=75000次乘法,显然,最好的次序是(A1A2)A3,乘法次数为7500次。
输入矩阵:
用p数组来表示矩阵,因为前一个矩阵的列是后一个矩阵的行,所以对于n个矩阵来讲只需输入n+1个数。1号矩阵 = p[0] * p[1] , 2号矩阵 = p[1] * p[2],…
我们假设1号矩阵到3号矩阵已经乘完,那么得到了一个10 * 25 的矩阵(10 * 50 50 * 20 20 * 25得到的最后矩阵为10 * 25 ),假设4号矩阵到5号矩阵也已经乘完,得到了25 * 100 的矩阵,那如果这两个矩阵相乘,需要多少次呢?矩阵的乘法是一行乘一列这样乘的,所以需要10 * 25 * 100 = 25000次乘法运算。10是一号矩阵的行,25是3号矩阵的列,100是5号矩阵的列,我们将矩阵乘法的最少次数保存到m[][]二维数组中,那么m[1][5]就表示1号矩阵乘到5号矩阵需要的次数,拿上面的例子来说,m[1][5]=m[1][3]+m[4][5]+p[0]*p[3]*p[5],意思是说 1号到5号矩阵乘法的次数=1号矩阵乘到3号矩阵的次数 + 4号矩阵乘到5号矩阵的次数 + 这两个乘法的次数(1号矩阵行 * 3号矩阵列 * 5号矩阵行 p[0]*p[3]*p[5]),而对于m[1][3]来说,也是类似于上面的求法,求出最小值。由此可以得出动态转移方程:
当 i = j 时:
m[i][j] = 0
当 i < j 时:
矩阵连乘问题,需要用动态规划来解决,为每个矩阵编号:
输入矩阵:
用p数组来表示矩阵,因为前一个矩阵的列是后一个矩阵的行,所以对于n个矩阵来讲只需输入n+1个数。1号矩阵 = p[0] * p[1] , 2号矩阵 = p[1] * p[2],…
我们假设1号矩阵到3号矩阵已经乘完,那么得到了一个10 * 25 的矩阵(10 * 50 50 * 20 20 * 25得到的最后矩阵为10 * 25 ),假设4号矩阵到5号矩阵也已经乘完,得到了25 * 100 的矩阵,那如果这两个矩阵相乘,需要多少次呢?矩阵的乘法是一行乘一列这样乘的,所以需要10 * 25 * 100 = 25000次乘法运算。10是一号矩阵的行,25是3号矩阵的列,100是5号矩阵的列,我们将矩阵乘法的最少次数保存到m[][]二维数组中,那么m[1][5]就表示1号矩阵乘到5号矩阵需要的次数,拿上面的例子来说,m[1][5]=m[1][3]+m[4][5]+p[0]*p[3]*p[5],意思是说 1号到5号矩阵乘法的次数=1号矩阵乘到3号矩阵的次数 + 4号矩阵乘到5号矩阵的次数 + 这两个乘法的次数(1号矩阵行 * 3号矩阵列 * 5号矩阵行 p[0]*p[3]*p[5]),而对于m[1][3]来说,也是类似于上面的求法,求出最小值。由此可以得出动态转移方程:
当 i = j 时:
m[i][j] = 0
当 i < j 时:
m[i][j] = min{ m[i][k] + m[k+1][j] + pi-1 * pk * pj } , i<=k<j
#include<bits/stdc++.h> using namespace std; int p[100]; int m[50][50]; int s[50][50]; void print(int i,int j) { if(i == j) { printf("A[%d]",i) ; return ; } printf("("); print(i,s[i][j]); print(s[i][j]+1,j); printf(")"); } int main() { int n; scanf("%d",&n); for(int i = 0;i<=n;i++) scanf("%d",&p[i]); for(int step=2;step<=n;step++) //链长 for(int left=1;left<=n-step+1;left++) { int right = left+step-1; m[left][right] = m[left+1][right]+p[left-1]*p[left]*p[right]; s[left][right] = left; for(int k=left+1;k<right;k++) if(m[left][k]+m[k+1][right]+p[left-1]*p[k]*p[right]<m[left][right]) m[left][right] = m[left][k]+m[k+1][right]+p[left-1]*p[k]*p[right],s[left][right] = k; } printf("%d\n",m[1][n]); print(1,n); }