这是一道环形区间DP问题,解决环形DP问题就是要把环形DP展开两圈,得出所有可能情况,我刚开始认为只在DP区间尾部加上头部就ok了,事实上这种情况还是没有考虑全,展开两圈就讨论所有情况。
这题的转移公式类似于矩阵乘法,只不过一个在寻求最小次数。而这个问题可以看作是求最大的乘法次数。
#include<iostream>
using namespace std;
//n是区间个数(矩阵个数)
//p[]是记录区间的开头和结尾
//t[]是一个二维数组,记录i到j的最大次数(最大能量值)
int n,p[100],t[100][100];
int main()
{
int i,j,k,mx=0;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>p[i];
p[n+i]=p[i];
//将环形DP空间展开成两圈
}
for(j=2;j<=n*2-1;j++)//最远一种可能就是到n*2-1,如果到了2*n就重复了第一个开始的那种情况
for(i=j-1;i>0&&j-i<n;i--)//j-i<n,因为在不同的情况下只能由4个矩阵相乘
for(k=i;k<j;k++)
t[i][j]=max(t[i][j],t[i][k]+t[k+1][j]+p[i]*p[k+1]*p[j+1]);
//转移公式,和矩阵相乘完全一样
for(i=1;i<=n;i++)
mx=max(mx,t[i][i+n-1]);
//遍历二维数组,求出最大次数,也就是最大能量
//这里不用遍历每个元素,因为这个区间尾部-头部必须长度为n,满足这个的才是要的题解
cout<<mx;
return 0;
}