时间限制: 1000 ms 内存限制: 524288 KB
提交数: 562 通过数: 150
【题目描述】
给定一个具有 N 个顶点的凸多边形,将顶点从 1 至 N 标号,每个顶点的权值都是一个正整数。将这个凸多边形划分成 N−2 个互不相交的三角形,试求这些三角形顶点的权值乘积和至少为多少。
【输入】
输入第一行为顶点数 N
第二行依次为顶点 1 至顶点 N 的权值。
【输出】
输出仅一行,为这些三角形顶点的权值乘积和的最小值。
【输入样例】
5
121 122 123 245 231
【输出样例】
12214884
【提示】
数据范围与提示:
对于 100% 的数据,有 N≤50,每个点权值小于 109 。
【来源】
这一题很明了是用区间dp解题,dp[i][j]=min(dp[i][j],dp[i][k]+dp[i][j]+a[i]*a[k]*a[j]);但是令人恶心的是它结果的数据范围太长了,用unsigned long long 都不能解出来,所以需要自己设计高精度计算。正好学习类,便重载了运算符。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
class long_int
{
public:
int array_[1000],dofe;
long_int(int x){for(int i=1;i<1000;i++)array_[i]=x;dofe=x*100+1;array_[0]=0;}
long_int(){dofe=0;for(int i=0;i<1000;i++)array_[i]=0;};
long_int(const long_int&a){
for(int i=1;i<=a.dofe;i++)
array_[i]=a.array_[i];
dofe=a.dofe;
}
void input()
{
char b;
dofe=0;
while(b=getchar(),!isdigit(b));
while(isdigit(b))
{
array_[++dofe]=b-'0';b=getchar();
}
}
long_int operator*(const long_int&a)
{
if((array_[1]==0&&dofe==1)||(a.array_[1]==0&&a.dofe==1))
return long_int(0);
long_int b;
for(int i=dofe;i>0;i--)
for(int h=a.dofe;h>0;h--)
{
b.array_[i+h]+=(array_[i]*a.array_[h]);
if(b.array_[i+h]>9){b.array_[i+h-1]+=(b.array_[i+h]/10);b.array_[i+h]%=10;}
}
if(b.array_[2]>10){b.array_[1]=b.array_[2]/10;b.array_[2]%=10;b.dofe=dofe+a.dofe;}
else if(!b.array_[1]){
b.dofe=dofe+a.dofe-1;
for(int i=1;i<=b.dofe;i++)
b.array_[i]=b.array_[i+1];
b.array_[b.dofe+1]=0;
}
else b.dofe=a.dofe+dofe;
return b;
}
long_int operator+(const long_int&a)
{
long_int b;
int maxx=max(a.dofe,dofe);
if(a.dofe>dofe)
for(int i=maxx;i>0;i--)
{
if(dofe-maxx+i>0)
b.array_[i]+=array_[dofe-maxx+i];
b.array_[i]+=a.array_[i];
if(b.array_[i]>9)
{b.array_[i-1]=b.array_[i]/10;b.array_[i]%=10;}
}
else
{
for(int i=maxx;i>0;i--)
{
if(a.dofe-maxx+i>0)
b.array_[i]+=a.array_[a.dofe-maxx+i];
b.array_[i]+=array_[i];
if(b.array_[i]>9)
{b.array_[i-1]=b.array_[i]/10;b.array_[i]%=10;}
}
}
if(b.array_[0])
{
b.dofe=++maxx;
for(int i=maxx;i>0;i--)
b.array_[i]=b.array_[i-1];
b.array_[0]=0;
}
else b.dofe=maxx;
return b;
}
bool operator==(const long_int &a)
{
for(int i=1;i<=a.dofe;i++)
if(a.array_[i]!=array_[i])
return false;
return true;
}
bool operator<(const long_int&a)
{
if((*this)==a)
return false;
if(dofe==a.dofe)
{
for(int i=1;i<=dofe;i++)
if(array_[i]<a.array_[i])
return true;
else if(array_[i]>a.array_[i])return false;
}
return dofe<a.dofe;
}
bool operator>(const long_int&a)
{
return(!((*this<a)||(*this==a)));
}
void print()
{
for(int i=1;i<=dofe;i++)
cout<<array_[i];
cout << " ";
}
};
long_int dp[200][200],multi_angle[200];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
multi_angle[i].input();
multi_angle[i+n]=multi_angle[i];
}
long_int maxx(9);
for(int i=1;i<=2*n;i++)
for(int o=1;o<=2*n;o++)
dp[i][o]=long_int(9);
for(int i=1;i<=2*n;i++)
dp[i][i]=dp[i][i+1]=long_int(0);
for(int len=3;len<=n;len++)
for(int i=1,j=len;j<=2*n;j++,i++)
{
for(int k=i+1;k<j;k++){
if(dp[i][j]>dp[i][k]+dp[k][j]+multi_angle[i]*multi_angle[k]*multi_angle[j])
{
dp[i][j]=dp[i][k]+dp[k][j]+multi_angle[i]*multi_angle[k]*multi_angle[j];
}
}
}
for(int i=1;i<=n;i++)
if(maxx>dp[i][i+n-1])
maxx=dp[i][i+n-1];
maxx.print();
}