凸多边形的划分

https://loj.ac/problem/10149

题目描述

  有一个\(N\)个顶点的多边形,每个顶点都有一个权值,求如何划分使得划分后的\(N-2\)个三角形的权值乘积和最小。

思路

  这题本意是要写高精度的,不过这不是重点。我们考虑用\(f[i][j]\)表示以\(i\)\(j\)之间的顶点所构成的多边形的最小权值乘积和,那么我们考虑作为\((i,j)\)这条边,必定有一个顶点与这条边形成一个三角形,我们枚举这个点,就把这个多边形分成了两个多边形,再加上这个三角形堆答案的贡献即可。

代码

#include <bits/stdc++.h>
using namespace std;
typedef __int128 ll;

ll read()
{
    ll res=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
    return res*w;
}
void write(ll x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
void writeln(ll x)
{
    write(x);
    putchar('\n');
}

ll f[110][110],a[110];
int main() 
{
    int n=read();
    for(int i=1;i<=n;i++)
        a[i]=read(),a[i+n]=a[i];
    memset(f,127,sizeof(f));
    for(int i=1;i<n*2;i++)
        f[i][i+1]=0;
    for(int len=3;len<=n;len++)
        for(int l=1;l<=n*2-len+1;l++)
        {
            int r=l+len-1;
            for(int k=l+1;k<r;k++)
                f[l][r]=min(f[l][r],f[l][k]+f[k][r]+a[l]*a[k]*a[r]);
        }
    ll ans=f[1][n];
    for(int i=1;i<=n;i++)
        ans=min(ans,f[i][i+n-1]);
    write(ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fangbozhen/p/11837587.html