#最优三角剖分
《算法竞赛入门经典(第2版)》讲解如下:
三角剖分是指用不相交的对角线把一个多边形分成若干个三角形。
例题9-11 Minimax Triangulation UVA - 1331
本题就是三角剖分的一个典型例题,求的是最大三角形的面积中,面积最大的三角形的面积最小的三角剖分所对应的这个最大的三角形面积。这道题需要注意的地方是,因为题目给出的图形不一定是凸多边形,参考上面的动态规划思路并结合题图可知,i-j可能不是多边形的对角线!
状态:d[i][j]表示顶点i,i+1,…,j-1,j形成的多边形的最优解
状态转移:d[i][j]=min{d[i[[j],max{d[i][k],d[k][j],s(i,j,k)}}
如上图所示多边形,当i=A,j=B,k=C时,这个三角形中包含多边形的一个顶点D,这是不合乎三角剖分的,并且这个三角形会影响最优解。另外,还有一种情况,当i=C,j=E,k=D时候,也是不合乎三角剖分的,但是这个三角形不可能是最优解,即他不会影响最优解,所以不必专门考虑此种情况了,只考虑包含多边形一个顶点的情形即可。
代码参考地址
#include<iostream>
#include<cmath>
#include<cstring>
#include<iomanip>
using namespace std;
const double INF=10e9;
const int maxn=55;
int n;
int m;
int x[maxn],y[maxn];
double d[maxn][maxn];
double dis(int i,int j){
return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
//海伦-秦九韶公式,已知三点坐标求三角形面积
double area(int i,int j,int k){
double a=dis(i,j),b=dis(i,k),c=dis(j,k);
double p=(a+b+c)/2.0;
return sqrt((p-a)*(p-b)*(p-c)*p);
}
bool check(int i,int j,int k){
for(int a=1;a<=m;a++){
if(i==a || j==a || k==a) continue;
double tmp=area(i,j,a)+area(i,k,a)+area(j,k,a)-area(i,j,k);
if(tmp<0) tmp=-tmp;
if(tmp<0.001) return false;
}
return true;
}
int main()
{
cin>>n;
while(n--){
cin>>m;
for(int i=1;i<=m;i++){
cin>>x[i]>>y[i];
}
memset(d,0,sizeof(d));
for(int i=m;i>=1;i--){
for(int j=i+2;j<=m;j++){
d[i][j]=INF;
for(int k=i+1;k<=j-1;k++){
if(check(i,j,k)){
d[i][j]=min(d[i][j],max(max(d[i][k],d[k][j]),area(i,j,k)));
}
}
}
}
cout<<fixed<<setprecision(1)<<d[1][m]<<endl;
}
return 0;
}