问题描述
有n个矩阵,大小分别为a0*a1, a1*a2, a2*a3, ..., a[n-1]*a[n],现要将它们依次相乘,只能使用结合率,求最少需要多少次运算。
两个大小分别为p*q和q*r的矩阵相乘时的运算次数计为p*q*r。
两个大小分别为p*q和q*r的矩阵相乘时的运算次数计为p*q*r。
输入格式
输入的第一行包含一个整数n,表示矩阵的个数。
第二行包含n+1个数,表示给定的矩阵。
第二行包含n+1个数,表示给定的矩阵。
输出格式
输出一个整数,表示最少的运算次数。
样例输入
3
1 10 5 20
1 10 5 20
样例输出
150
数据规模和约定
1<=n<=1000, 1<=ai<=10000。
C
#include <stdio.h>
long long N=3;
long long matri[1002]={1,10,5,20};
long long record[1002][1002];
/*int fun(int start,int end){
int i=0;
int min=9999999999,temp=0;
if(start==end||start<=0||end>N) return 0;
if(record[start][end]!=0) return record[start][end];
for(i=start;i<end;i++){
temp=fun(start,i)+fun(i+1,end)+matri[start-1]*matri[i]*matri[end];
if(min>temp)
min=temp;
}
record[start][end]=min;
return min;
} */ //效率低 只有40分
void fun02(){
long long i,j,k=0,len=0;
long long temp=0;
for(i=0;i<=N;i++) for(j=0;j<=N;j++) record[i][j]=0;
for(len=2;len<=N;len++){
for(i=1;i<=N-len+1;i++){
j=i+len-1;
record[i][j]=9999999999999;
for(k=i;k<=j-1;k++){
temp=record[i][k]+record[k+1][j]+matri[i-1]*matri[k]*matri[j];
if(temp<record[i][j])
record[i][j]=temp;
}
}
}
} /* */
int main()
{
long long i=0,j=0;
scanf("%lld",&N);
for(i=0;i<=N;i++) scanf("%lld",&matri[i]); /* */
fun02();
printf("%lld\n",record[1][N]);
return 0;
}
C++
#include<iostream>
using namespace std;
int main()
{
int n;
long long l,answer[1001][1001], i, j, k,a[1001],temp;
cin >> n;
for (i = 0; i <= n; i++)
cin >> a[i];
for (i = 1; i <= n; i++) //第一阶段
answer[i][i] = 0; //赋初值
for (l = 2; l <= n; l++) //其他n-1个阶段
{
for (i = 1; i <= n - l+1; i++) //n-1+l有关的表达式
{
j = i +l-1;
answer[i][ j] = 1000000000000;
for (k = i; k <= j - 1; k++)
{
temp = answer[i][k] + answer[k + 1][j] + a[i - 1] * a[k] * a[j]; //状态转移方程
if (temp < answer[i][j])
answer[i][j] = temp; //由子问题最优解求解整个方案
}
}
}
cout << answer[1][n];
}