UVA

题目链接

把一个多边形剖分成若干个三角形,使得其中最大的三角形面积最小。

比较经典的一道dp问题

设dp[l][r]为把多边形[l,r]剖分成三角形的最大三角形面积中的最小值,则$dp[l][r]=min{dp[l][i]+dp[i][r]+area(l,i,r)}$

注意:

1.由于多边形的点不一定按顺时针或者逆时针排列,需要按点的顺序计算一遍多边形的面积,如果为负说明是顺时针排列,需要反转一下。

2.进行剖分的时候有可能会“出界”,但无需进行线段相交判断,只需在计算的面积出现负数时返回inf即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef double db;
 5 const int N=50+10;
 6 const db inf=1e18;
 7 struct P {
 8     db x,y;
 9     P operator-(P& b) {return {x-b.x,y-b.y};}
10 } p[N];
11 db cross(P a,P b) {return a.x*b.y-a.y*b.x;}
12 int n;
13 db calarea() {
14     db ret=0;
15     for(int i=1; i<n-1; ++i)ret+=cross(p[i]-p[0],p[i+1]-p[0]);
16     return ret/2;
17 }
18 db calarea(int l,int m,int r) {
19     return cross(p[l]-p[r],p[m]-p[r])/2;
20 }
21 db d[N][N];
22 db dp(int l,int r) {
23     if(r-l<2)return 0;
24     db& ret=d[l][r];
25     if(ret>=0)return ret;
26     ret=inf;
27     for(int i=l+1; i<r; ++i) {
28         db area=calarea(l,i,r);
29         if(area>0)ret=min(ret,max(dp(l,i),max(dp(i,r),area)));
30     }
31     return ret;
32 }
33 
34 int main() {
35     int T;
36     for(scanf("%d",&T); T--;) {
37         scanf("%d",&n);
38         for(int i=0; i<n; ++i)scanf("%lf%lf",&p[i].x,&p[i].y);
39         if(calarea()<0)reverse(p,p+n);
40         memset(d,200,sizeof d);
41         printf("%.1f
",dp(0,n-1));
42     }
43     return 0;
44 }
原文地址:https://www.cnblogs.com/asdfsag/p/10451171.html