C时间限制:3000 毫秒 | C内存限制:3000 Kb
题目内容:
n个矩阵A1,A2,...,An, ,如果其维度分别为d0xd1, d1xd2, ...dn-1xdn,则可以进行连乘运算A1A2A3..An . 连乘运算可以采取不同的顺序进行,如(A1A2)A3 和 A1(A2A3),这两种顺序的消耗乘法计算量是不同的,前者是 d0.d1.d2+d0.d2.d3,后者d0.d1.d3+d1.d2.d3. 第1步选择哪两个,第2步又选择哪两个,一直到最后算出结果需要做n-1次决定。其中有一种计算顺序使得 A1A2A3..An总的乘法计算量最小。
输入描述
第一行输入n 第二行输入维度向量d0,d1,...dn
输出描述
输出所需的最少乘法次数。
输入样例
4 2 3 2 4 3
输出样例
48
思路: 区间dp, 设dp[i][j]表示第i个矩阵到第j个矩阵之间合并的最少相乘次数
则递归方程为: dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + d[i-1]*d[k]*d[j]); i < k < j;
需要知道相邻矩阵的乘法规则:A1(x1, y1)* A2(x2, y2) = x1 * y1 * y2;(x表示行,y表示列)
#include <iostream>
using namespace std;
int dp[100][100];
int a[100];
int n;
int fun(int i, int j){
if(i == j)
return dp[i][j];
if(i == j - 1)
return dp[i][j] = a[i - 1] * a[i] * a[j];
if(i < j - 1){
dp[i][j] = 10000000;
for(int k = i + 1; k < j; k++)
dp[i][j] = min(dp[i][j], fun(i, k) + fun(k + 1, j) + a[i - 1] * a[j] * a[k]);
}
return dp[i][j];
}
int main(){
cin >> n;
for(int i = 0; i <= n; i++)
cin >> a[i];
cout << fun(1, n);
return 0;
}