解题思路:给定我们一个凸多边形,首先我们要知道如何对这个多边形进行划分,我们可以选择的两个点,然后在这两个点之间再选择一个点,这样就构成了一个三角形,这样就把这个凸多边形分成了2个多边形和一个三角形,因为分成的两个多边形之间没有联系,所以这是我们用区间DP来做这道题的基础,我们假设出数组f[i][j]表示从第i个顶点到第j个顶点构成的多边形通过划分得到的所有三角形顶点权值乘积之和的最小值,那么它可以由谁来得到呢?设置中间变量k,i<k<j,选择i,j,k三个点构成一个三角形,并将整个大多边形分割成了一个三角形和两个小凸多边形,而小凸多边形我们可以用相同的方法来解决,所以得到递推方程:f[i][j]=min(f[i][k]+f[k][j]+w[i]*w[j]*w[k]),i<k<j,我们要从规模小的问题一步一步向大规模问题来递推,所以设置变量len来控制问题的规模,因为规模最小就是只有一个三角形,所以len可以从3开始取,分析到这里其实不难发现就是一个区间DP问题的小变形,再看数据量,我们会惊奇地发现数据会爆long long ,所以对于中间过程中数据的计算要用到高精度,其实我感觉这个题的考察重点就是用高精度来求解,思路并不难,上代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=110;
const int M=35;
int w[N];
long long f[N][N][M];
int n;
void add(long long a[],long long b[])
{
long long c[M];
memset(c,0,sizeof c);
int t=0;
for(int i=0;i<M;i++)
{
t+=a[i]+b[i];
c[i]=t%10;
t/=10;
}
memcpy(a,c,sizeof c);
}
void mul(long long a[],long long b)
{
long long c[M];
memset(c,0,sizeof c);
long long t=0;
for(int i=0;i<M;i++)
{
t+=a[i]*b;
c[i]=t%10;
t/=10;
}
memcpy(a,c,sizeof c);
}
int cmp(long long a[],long long b[])
{
for(int i=M-1;i>=0;i--)
if(a[i]>b[i])
return 1;
else if(a[i]<b[i])
return -1;
return 0;
}
void print(long long a[])
{
int k=M-1;
while(k>=0&&a[k]==0)
k--;
while(k>=0)
cout<<a[k],k--;
cout<<endl;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>w[i];
long long temp[M];
for(int len=3;len<=n;len++)
for(int i=1;i+len-1<=n;i++)
{
int j=i+len-1;
f[i][j][M-1]=1;//把初始的数组设成一个比较大的数
for(int k=i+1;k<j;k++)
{
memset(temp,0,sizeof temp);
temp[0]=w[i];
mul(temp,w[k]);
mul(temp,w[j]);
add(temp,f[i][k]);
add(temp,f[k][j]);
if(cmp(f[i][j],temp)>0)
memcpy(f[i][j],temp,sizeof temp);
}
}
print(f[1][n]);
return 0;
}