您的位置:首页 > 其它

蓝桥杯 算法提高 矩阵乘法 【经典区间dp】

2018-02-16 17:34 381 查看

算法提高 矩阵乘法

时间限制:3.0s 内存限制:256.0MB

问题描述

  有n个矩阵,大小分别为a0*a1, a1*a2, a2*a3, …, a[n-1]*a
,现要将它们依次相乘,只能使用结合率,求最少需要多少次运算。

  两个大小分别为p*q和q*r的矩阵相乘时的运算次数计为p*q*r。

输入格式

  输入的第一行包含一个整数n,表示矩阵的个数。

  第二行包含n+1个数,表示给定的矩阵。

输出格式

  输出一个整数,表示最少的运算次数。

样例输入

3

1 10 5 20

样例输出

150

数据规模和约定

  1<=n<=1000, 1<=ai<=10000。

题意: 给你数组p,给你n个矩阵,第i个矩阵 记为Ai,其长宽为:p[i−1]∗p[i]Ai,其长宽为:p[i−1]∗p[i],让你计算n个矩阵相乘后的最小运算数,且两个大小分别为p*q和q*r的矩阵相乘时的运算次数计为p*q*r。

分析:此题是很经典的区间dp问题,先简单普及下,矩阵相乘的运算次数

以矩阵链{A1,A2,A3}为例,假设三个矩阵的规模分别为10X100,100X5和5X50。

以矩阵链 {A1,A2,A3} 为例,假设三个矩阵的规模分别为10X100,100X5和5X50。

①以((A1*A2)*A3)方式划分,乘法执行次数为:10*100*5+10*5*50=5000+2500=7500次

我们可以发现,对于同样的矩阵链A1,A2,A3相乘而言,不同的划分,乘法次数居然相差10倍。

我们用
dp[l][r]代表矩阵l 连续相乘到 r 的最小运算数,我们可以得到动态方程为

dp[l][r] = min(dp[l][r],dp[l][k] + dp[k + 1][r] + a[l - 1]*a[k]*a[r]


其中 k 代表将
{l···r}
原矩阵分割成
{l··k}*{k+1···r}
两小矩阵相乘

具体原理请看这里

参考代码

#include<bits/stdc++.h>

using namespace std;

#define ll long long
const ll INF_LL = 9223372036854775807LL;

const ll maxn = 1e3 + 10;

ll a[maxn];
ll dp[maxn][maxn];
int main(){
int n;
scanf("%d",&n);
for (int i = 0; i <= n; i++) {
scanf("%d", &a[i]);
}
for (int i = 0; i <= n; i++) {
for (int j = i; j <= n; j++) {
if(i == j) {
dp[i][j] = 0;
} else {
dp[i][j] = INF_LL;
}
}
}
for (int i = 2; i <= n; i++) {
for (int l = 1; l <= n - i + 1; l++) {
int r = l + i - 1; // 枚举 左端 和 右端
for (int k = l; k < r; k++) { //枚举分割点
dp[l][r] = min (dp[l][r], dp[l][k] + dp[k + 1][r] + a[l - 1]*a[k]*a[r]);
}
}
}
cout<<dp[1]
<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: