1069. 凸多边形的划分

题目链接

1069. 凸多边形的划分

给定一个具有 \(N\) 个顶点的凸多边形,将顶点从 \(1\)\(N\) 标号,每个顶点的权值都是一个正整数。

将这个凸多边形划分成 \(N−2\) 个互不相交的三角形,对于每个三角形,其三个顶点的权值相乘都可得到一个权值乘积,试求所有三角形的顶点权值乘积之和至少为多少。

输入格式

第一行包含整数 \(N\),表示顶点数量。

第二行包含 \(N\) 个整数,依次为顶点 \(1\) 至顶点 \(N\) 的权值。

输出格式

输出仅一行,为所有三角形的顶点权值乘积之和的最小值。

数据范围

\(N≤50,\)
数据保证所有顶点的权值都小于\(10^9\)

输入样例:

5
121 122 123 245 231

输出样例:

12214884

解题思路

区间dp

  • 状态表示:\(f[l][r]\) 表示区间 \([l,r]\) 内构成的凸多边形的最少权值之和

  • 状态计算:\(f[l][r]=min(f[l][r],f[l][k]+f[k][r]+a[l]*a[r]*a[k])\),其中 \(k\) 为区间 \([l,r]\) 上的点

分析:枚举区间端点 \(l\)\(r\) 和区间内的哪个点形成一个三角形
注意:这里不用破环成链,因为区间 \([1,n]\) 就代表了整个凸多边形,\(1\)\(n\) 两个端点总是要和剩余一点组成三角形,这样的状态计算任何一种三角形都考虑进去了
另外,这里会爆long long,但不超过__int128范围

  • 时间复杂度:\(O(n^3)\)

代码

// Problem: 凸多边形的划分
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/description/1071/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}
template <typename T>
void print(T x) {
    if (x < 0) putchar('-'), x = -x;
    if (x < 10) putchar(x + 48);
    else print(x / 10), putchar(x % 10 + 48);
}


const int N=110;
int n;
__int128 f[N][N],a[N];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    	read(a[i]);
    for(int i=1;i<=n;i++)f[i][i+2]=a[i]*a[i+1]*a[i+2];
    for(int len=4;len<=n;len++)
    	for(int l=1;l+len-1<=n;l++)
    	{
    		__int128 r=l+len-1;
    		f[l][r]=1e30;
    		for(int k=l+1;k<=r-1;k++)
    		    f[l][r]=min(f[l][r],f[l][k]+f[k][r]+a[l]*a[r]*a[k]);
    	}
    __int128 res=1e30;
    print(f[1][n]);
    return 0;
}
posted @ 2022-03-16 09:46  zyy2001  阅读(136)  评论(0编辑  收藏  举报