问题引入
给出一个n各顶点的凸多边形,有很多种方法可以对它进行三角剖分,即用n-3条互不相交的对角线把凸多边形分成n-2个三角形。为每个三角形规定一个权函数 w ( i , j , k ) w(i,j,k) w(i,j,k),求让所有三角形权值和最大的方案
状态转移
如果允许自由切割,那么多边形的顶点在原多边形中可以随意选取,很难定义成简洁的状态,无法找到递推的联系。如图选取了BCEG,这样的状态无法表示,因此我们需要将决策规范化
定义 d ( i , j ) d(i,j) d(i,j)为子多边形 i , i + 1 , . . . , j − 1 , j i,i+1,...,j-1,j i,i+1,...,j−1,j的最优值,则边 i − j i-j i−j的最优解一定含有点 i i i和 j j j,而这样的切割方法保证了每次切出来的多边形组成的点的编号都是连续的,于是我们就可以用两个元素表示一个多边形的状态
即状态转移方程为:
d ( i , j ) = m a x ( d ( i , j ) , d ( i , k ) + d ( k , j ) + w ( i , j , k ) ) {d(i,j)~=~max(d(i,j),d(i,k)+d(k,j)+w(i,j,k))} d(i,j) = max(d(i,j),d(i,k)+d(k,j)+w(i,j,k)), i < k < j i<k<j i<k<j
边界 d ( i , i + 1 ) = 0 d(i,i+1)=0 d(i,i+1)=0,则该问题的解为 d ( 0 , n − 1 ) d(0,n-1) d(0,n−1)
时间复杂度 O ( n 3 ) O(n^3) O(n3)
特殊情况
如果给出的多边形不一定是凸多边形,那么需要注意选取了 i , j , k i,j,k i,j,k三个点后,如果 i − k i-k i−k或 j − k j-k j−k两个对角线的任意一条与其他边相交,那么这个点就不能选,如何判断:
选定一个 k k k的时候,只需要看 i , j , k i,j,k i,j,k三点组成的三角形内部是否有点,如果有,那么必然会相交。如果一个点在三角形内部,那么将它与三角形三个顶点连线一定可以把三角形切分成3个三角形,且3个三角形面积之和就是这个大三角形的面积,根据面积作差来检验
const double eps=?;
const int maxn=?;
struct Point{
//...
}p[maxn];
inline int dcmp(double d){
if(fabs(d)<eps) return 0;
return d>0?1:-1;
}
double area(int a,int b,int c){ //Point为计算几何中的点表示
Point x=p[b]-p[a],y=p[c]-p[a];
double s=(x^y)/2.0;
return fabs(s);
}
bool check(int a,int b,int c){
for(int i=0;i<n;i++){
if(i==a || i==b || i==c) continue;
double s=area(a,b,i)+area(a,c,i)+area(b,c,i)-area(a,b,c);
if(dcmp(s)==0) return 0;
}
return 1;
}