凸多边形的三角剖分【区间dp】

 给定一具有N个顶点(从1到N编号)的凸多边形,每个顶点的权均已知。问如何把这个凸多边形划分成N-2个互不相交的三角形,使得这些三角形顶点的权的乘积之和最小?

样例输入

5
121 122 123 245 231

样例输出

12214884

这道题有一个有趣的性质,如果剖分出的多边形是最优的,那么他的子多边形的剖分也是最优的,以下是证明

设多边形的顶点为 v1,v2,·····,vn
我们在一个多边形中画出一个三角形,这个多边形会被分为一个三角形和两个子多边形。
假设这个三角形 vi vk vj(i < k < j)权值为 x
两个子多边形剖分后的权值分别为a,b, 原多边形剖分的权值为c

我们要做的是,证明 c 最优时, a,b 一定也是最优的。(k确定时,两个子多边形形状确定)
设 a 不是最优的,b是最优的,则存在一最优解 a' < a
a’ + b + x < c 此时 c 不是最优的。
同理 b 不为最优时, c也不是最优的。
所以a,b都最优时,c才最优

这就是最优子结构性质,基于这个性质我们可以进行区间dp

枚举起点 i,终点 j, 三角形顶点 k (i < k < j)
设dp[i][j]表示多边形 vi ······· vj 的最优剖分, a[i]为点 i 的权值
动态转移方程 dp[i][i]=max(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[k]*a[j])
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #define int long long
 6 const int maxn = 55, inf = 0x3f3f3f3f;
 7 using namespace std;
 8 int n, k, f[maxn][maxn], a[maxn];
 9 char s[maxn];
10 signed main(){
11     scanf("%lld", &n);
12     for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
13     memset(f, 0x3f, sizeof(f));
14     for(int i=1; i<=n; i++) f[i][i] = f[i][i+1] = 0;//不能构成多边形
15     for(int j=2; j<=n; j++){
16         for(int i=j-2; i>0; i--){
17             for(int k=i+1; k<j; k++){
18                 f[i][j] = min(f[i][j], f[i][k]+f[k][j]+a[i]*a[k]*a[j]);
19             }
20         }
21     }
22     printf("%lld\n", f[1][n]);
23     return 0;
24 }
 




 

猜你喜欢

转载自www.cnblogs.com/hzoi-poozhai/p/12661951.html