1. 程式人生 > >區間DP——凸多邊形的三角形劃分

區間DP——凸多邊形的三角形劃分

問題 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;
}