1571:【例 3】凸多边形的划分

时间限制: 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();


}



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值