Description
Input
n表示矩阵的个数(<=100)
n+1个数,表示矩阵(<=100)
Output
最小的乘法次数
Sample Input
5
5 10 4 6 10 2
Sample Output
348
思路
那么这道题有3种做法:
1&2:设dp[i][j]为从第i个开始的j-1个矩阵的最小乘次数
d p [ i ] [ j ] = m i n ( d p [ i ] [ j ] , d p [ i ] [ k − 1 ] + d p [ k ] [ j ] + a [ i ] ∗ a [ k ] ∗ a [ j + 1 ] ) ( 1 < = i < = n , 1 < = l < n , j = i + l , i < k < = j ) dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k][j]+a[i]*a[k]*a[j+1])(1<=i<=n,1<=l<n,j=i+l,i<k<=j) dp[i][j]=min(dp[i][j],dp[i][k−1]+dp[k][j]+a[i]∗a[k]∗a[j+1])(1<=i<=n,1<=l<n,j=i+l,i<k<=j)
1:先枚举长度,再枚举起点
code:
#include<iostream>
#include<algorithm>
using namespace std;
int n,a[300],dp[300][300];
int main()
{
cin>>n;
for (int i=1;i<=n+1;i++)
{
cin>>a[i];
}
//for (int i=1;i<=n;i++) dp[i][i]=1;
for (int l=1;l<n;l++) for (int i=1,j=i+l;i<=n-l;i++,j=i+l)
{
dp[i][j]=0x7f7f7f7f;
for (int k=i+1;k<=j;k++)
{
dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k][j]+a[j+1]*a[i]*a[k]);
}
}
cout<<dp[1][n];
return 0;
}//记住,3年OI一场空,不删检查见祖宗
2.枚举边界
code:
#include<iostream>
#include<algorithm>
using namespace std;
int n,a[300],dp[300][300];
int main()
{
cin>>n;
for (int i=1;i<=n+1;i++)
{
cin>>a[i];
}
//for (int i=1;i<=n;i++) dp[i][i]=1;
for (int i=n-1;i>=1;i--) for (int j=i+1;j<=n;j++)
{
dp[i][j]=0x7f7f7f7f;
for (int k=i+1;k<=j;k++)
{
dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k][j]+a[j+1]*a[i]*a[k]);
}
}
cout<<dp[1][n];
return 0;
}
3.设dp[i][j]为从i起往下数j个的最优值
f [ i ] [ j ] = m i n ( f [ i ] [ j ] , f [ i + k ] [ j − k ] + f [ i ] [ k ] + a [ i ] ∗ a [ k + i ] ∗ a [ j + i ] ) f[i][j]=min(f[i][j],f[i+k][j−k]+f[i][k]+a[i]*a[k+i]*a[j+i]) f[i][j]=min(f[i][j],f[i+k][j−k]+f[i][k]+a[i]∗a[k+i]∗a[j+i])
枚举长度,枚举起点
code:
#include<iostream>
#include<algorithm>
using namespace std;
int n,a[300],dp[300][300];
int main()
{
cin>>n;
for (int i=1;i<=n+1;i++)
{
cin>>a[i];
}
for (int l=2;l<=n;l++) for (int i=1;i<=n-l+1;i++)
{
dp[i][l]=0x7f7f7f7f;
for (int k=1;k<l;k++)
{
dp[i][l]=min(dp[i][l],dp[i+k][l-k]+dp[i][k]+a[i]*a[l+i]*a[k+i]);
}
}
cout<<dp[1][n];
return 0;
}