题目大意:有n个矩阵,大小分别为a0*a1, a1*a2, a2*a3, ..., a[n-1]*a[n],现要将它们依次相乘,只能使用结合率,求最少需要多少次运算。两个大小分别为p*q和q*r的矩阵相乘时的运算次数计为p*q*r。
题目分析:本题是计算一系列连乘矩阵的最小运算次数。这是一道非常经典的动态规划的题目。
动态规划算法的特点是:
1.把原始问题划分成一系列子问题
2.求解每个子问题仅一次,并将其结果保存在一个表中,以后用到时直接存取,不重复计算,节省计算时间。
3.自底向上计算
回到本题上来,本题解法:
设cost[i][j]表示计算第i个矩阵Ai与第j个矩阵Aj所需的代价,矩阵Ai=a(i-1)*ai,矩阵Aj=a(j-1)*aj
那么,我们可以得到cost的代价转换方程:
当i==j时,cost[i][j]=0;
当i<j时,cost[i][j]=min{cost[i][k]+cost[k+1][j]+a[i-1]*a[k]*a[j]},其中i<=k<j.
也就是说,可以在Ai与Aj之间的任意第k个位置切一刀,有j-i中切法,比较这些切法,求出最小值,即最小代价
本题需要注意的地方有:数组类型要设置为long long型; 一个最大值的边界要尽量大一点,如1e18.
另外,本题的最后一组样例很容易不通过,得90分。我是通过在最里层循环将u=i+j,最后才AC
代码展示:
#include <iostream>
using namespace std;
int main(){
int n; //矩阵个数
cin>>n;
long long a[1008];
long long cost[1008][1008]; //cost[i][j]表示第i个矩阵到第j个矩阵所需代价
for(int i=0;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++)
cost[i][i] = 0;
long long temp;
int u = 0;
for(int i=1;i<=n;i++){ //i表示cost数组中横纵坐标之差,按对角线方向往上扫
for(int j=1;j<=n-i;j++){
u = j+i;
cost[j][u] = 1e18;
for(int k=j;k<u;k++){
temp = cost[j][k]+cost[k+1][u]+a[j-1]*a[k]*a[u];
if(temp<cost[j][j+i]){
cost[j][j+i] = temp;
}
}
}
}
cout<<cost[1][n]<<endl;
return 0;
}