A.矩阵链相乘问题
本题用到了动态规划的思想,是关于最优子问题的最好例题,具体想法是当前处理的问题存在最优子问题,我们可以从最底层来开始,并且之后我们在处理过程中我们还要借助前一层已经解决过的问题来解决当前子问题。
本题思路:
所以我们就得到了状态转移方程为
:DP[i][j]=min{DP[i][k]+DP[k+1][j]+Pi-1*Pk*Pj(i<=k<j)}
我们枚举i和j之间的k找到状态方程的最小值就行
具体我们列举状态矩阵:
所以我们可以通过枚举 括号的括的个数从小到大递推,也可以通过从矩阵的对角线处递推即可。
这里我们给出两种方法:
//方法一:通过括号中的个数枚举
#include<bits/stdc++.h>
using namespace std;
int dp[1010][1010]={0};
int main()
{
int num;
cin>>num;
int p[num+1];
for(int i=0;i<=num;i++)cin>>p[i];
int n=num;
for(int r=2;r<=num;r++)//我们枚举括号中的矩阵个数,两以上个有效,一个的时候为0
{
for(int i=1;i<=n-r+1;i++)//i是左边界,j是右边界,j最大为num,i最大为num-r+1
{
int j=i+r-1;
dp[i][j]=dp[i][i]+dp[i+1][j]+p[i-1]*p[i]*p[j];
for(int k=i+1;k<j;k++)
{
int temp=dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j];
dp[i][j]=min(dp[i][j],temp);
}
}
}
cout<<dp[1][num];
}
//方法二:通过矩阵的对角线开始枚举
#include<bits/stdc++.h>
using namespace std;
int dp[1010][1010]={0};
int main()
{
int num;
cin>>num;
int p[num+1];
for(int i=0;i<=num;i++)cin>>p[i];
for(int i=num-1;i>=1;i--)//我们从矩阵对角线开始遍历
{
for(int i1=i+1;i1<=num;i1++)//每次我们从第一个开始访问
{ dp[i][i1]=dp[i][i]+dp[i+1][i1]+p[i-1]*p[i]*p[i1];
for(int k=i+1;k<i1;k++)
{
int temp=dp[i][k]+dp[k+1][i1]+p[i-1]*p[k]*p[i1];
dp[i][i1]=min(temp,dp[i][i1]);
}
}
}
cout<<dp[1][num];
}