问题 C: 凸多边形的三角形划分
时间限制: 1 Sec 内存限制: 128 MB
提交: 4 解决: 2
[提交][状态][讨论版][命题人:add_oopscyc]
题目描述
给定一具有N个顶点(从1到N编号)的凸多边形,每个顶点的权均已知。问如何把这个凸多边形划分成N-2个互不相交的三角形,使得这些三角形顶点的权的乘积之和最小?
输入
第一行 顶点数N(N<50)。
第二行 N个顶点(从1到N)的权值,权值为小于32768的整数。
输出
各三角形顶点的权的乘积之和最小值。
样例输入
5 121 122 123 245 231
样例输出
12214884
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
int n,j;
long long int f[110][110][110],a[110],s1[110],s2[110],s3[110];
void mark(long long int c[])//高精度处理
{
for(int i=1;i<=c[0];i++)
{
c[i+1]+=c[i]/10000;
c[i]%=10000;
}
while(c[c[0]+1])
{
c[0]++;
c[c[0]+1]+=c[c[0]]/10000;
c[c[0]]%=10000;
}
}
void mul(long long int a1,long long int a2,long long int a3,long long int c[])
//将a1*a2*a3的值存储在数组c中,高精度乘法
{
c[0]=c[1]=1;
for(int i=1;i<=c[0];i++)
c[i]*=a1;
mark(c);
for(int i=1;i<=c[0];i++)
c[i]*=a2;
mark(c);
for(int i=1;i<=c[0];i++)
c[i]*=a3;
mark(c);
}
void add(long long int a[],long long int b[],long long int c[])
//高精度加法
{
c[0]=max(a[0],b[0]);
for(int i=1;i<=c[0];i++)
c[i]=a[i]+b[i];
mark(c);
}
int compare(long long int a[],long long int b[])
{
if(a[0]<b[0])
return 0;
if(a[0]>b[0])
return 1;
for(int i=a[0];i>=1;i--)
if(a[i]<b[i])return 0;
else if(a[i]>b[i])return 1;
return 0;
}
void print()//输出答案
{
cout<<f[1][n][f[1][n][0]];
for(int i=f[1][n][0]-1;i>=1;i--)
{
cout<<f[1][n][i]/1000;
cout<<f[1][n][i]/100%10;
cout<<f[1][n][i]/10%10;
cout<<f[1][n][i]%10;
}
cout<<endl;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j][0]=0;//初始化
for(int num=2;num<=n-1;num++)//划分次数
for(int i=1;i<=n-num;i++)//起点
{
j=i+num;//终点
f[i][j][0]=60;
for(int k=i+1;k<=j-1;k++)
{
memset(s1,0,sizeof(s1));
memset(s2,0,sizeof(s2));
memset(s3,0,sizeof(s3));
mul(a[i],a[k],a[j],s1);//将三角形顶点权值相乘,s1=a[i]*a[k]*a[j]
add(f[i][k],f[k][j],s2);//s2=f[i][k]+f[k][j]
add(s1,s2,s3);//s3=s1+s2=a[i]*a[k]*a[j]+f[i][k]+f[k][j]
if(compare(f[i][j],s3))
memcpy(f[i][j],s3,sizeof(s3));//f[i][j]=min(f[i][j],s3),求最小值
}
}
print();//输出答案
return 0;
}