凸多边形最优三角剖分

凸多边形最优三角剖分

题目:

​ 多边形是平面上一条分段线性的闭曲线。凸多边形满足:边界上或内部的任意两点所连成的直线段上所有点均在凸多边形内部或边界上。通常用多边形顶点的逆时针序列表示凸多边形,即 P = { v 0 , v 1 , . . . , v n − 1 } P=\{v_0,v_1,...,v_{n-1}\} P={v0,v1,...,vn1} 表示具有n条边 v 0 v 1 、 v 1 v 2 、 . . . 、 v n − 1 v n v_0v_1、v_1v_2、...、v_{n-1}v_{n} v0v1v1v2...vn1vn 的凸多边形。其中,约定 v 0 = v n v_0=v_n v0=vn

​ 若 v i v_i vi v j v_j vj 是多边形上不相邻的两个顶点,则线段 v i v j v_iv_j vivj 称为多边形的一条弦。弦 v i v j v_iv_j vivj 将多边形分割成两个多边形 { v i , v i + 1 , v j } \{v_i,v_{i+1},v_j\} {vi,vi+1,vj} { v j , v j + 1 , v i } \{v_j,v_{j+1},v_i\} {vj,vj+1,vi}

​ 多边形的三角剖分是指将多边形分割成互不相交的三角形的弦的集合T。下图就是不同的三角剖分:

image-20221031012717885

规定三角形上各种各样的权值函数 w ( v i v j v k ) = ∣ v i v j ∣ + ∣ v i v k ∣ + ∣ v k v i ∣ w(v_iv_jv_k)=\vert v_iv_j \vert + \vert v_iv_k \vert + \vert v_kv_i \vert w(vivjvk)=vivj+vivk+vkvi 。其中 ∣ v i v j ∣ \vert v_iv_j \vert vivj 为两点的欧氏距离,现要求出全职最小的三角剖分,即最优三角剖分。

分析:

​ 这题类似于矩阵连乘的最优计算次序问题,等价于矩阵链的最优完全加括号方式,可以用动态规划来解。

最优子结构性质:

​ 若 n+1 边形 P = { v 0 , v 1 , . . . , v n } P=\{v_0,v_1,...,v_n\} P={v0,v1,...,vn} 的最优三角剖分 T 包含三角形 v 0 v k v n ( 1 ≤ k ≤ n − 1 ) v_0v_kv_n \quad (1 \leq k \leq n-1) v0vkvn(1kn1) ,则 T 的权为三角形 v 0 v k v n v_0v_kv_n v0vkvn 的权、子多边形 { v 0 , v 1 , . . . , v k } \{v_0,v_1,...,v_k\} {v0,v1,...,vk} { v k , v k + 1 , . . . , v n } \{v_k,v_k+1,...,v_n\} {vk,vk+1,...,vn} 的权之和。可以断言,由 T 确定的这两个子多边形的三角剖分也是最优的。因为若存在更小权的三角剖分,将导致 T 不是最优的三角剖分,与假设矛盾。

递归定义:

​ 定义 t[i][j] (1<=i<j<=n) 为凸子多边形 { v i − 1 , v i , . . . , v j } \{v_{i-1},v_i,...,v_j\} {vi1,vi,...,vj} 的最优三角剖分对应得权函数值。设退化的多边形 { v i − 1 , v i } \{v_{i-1},v_i\} {vi1,vi} 具有权值0。据此定义,要计算的凸 n+1 边形 P 的最优权值为 t[1][n] 。根据上述分析,递归定义式为:
t [ i ] [ j ] = { 0 i = j min ⁡ i ≤ k ≤ j { t [ i ] [ k ] + t [ k + 1 ] [ j ] + w ( v i − 1 v k v j ) } i < j t[i][j]= \begin{cases} 0 && i=j \\ \min_{i \leq k \leq j} \{t[i][k]+t[k+1][j]+w(v_{i-1}v_kv_j)\} && i<j \end{cases} t[i][j]={0minikj{t[i][k]+t[k+1][j]+w(vi1vkvj)}i=ji<j

实现:

计算权值:

/**
凸多边形最优三角剖分
n: 顶点个数
t: 剖分的权值矩阵
s: 剖分路径矩阵
*/
void minWeightTriangulation(int n, int **t, int **s){
	// 初始化对角线位置
	for(int i=1; i<=n; i++){
		t[i][i] = 0;
	}
	// 斜对角线索引
	for(int r=2; r<=n; r++){
		// 行
		for(int i=1; i<=n-r+1; i++){
			// 列
			int j = i + r - 1;
			// 将权重初始化为 {v_i, v_i} {v_i, v_i+1,..., v_j}时的权重
			t[i][j] = t[i+1][j] + w(i-1, i, j);
			s[i][j] = i;
			// 寻找最大切分点
			for(int k=i+1; k<j; k++){
				int u = t[i][k] + t[k+1][j] + w(i-1, k, j);
				if(u < t[i][j]){
					t[i][j] = u;
					s[i][j] = k;
				}
			}
		}
	}
}

**计算权重策略:**根据题目定义,这边未给出明确的方法

/*
权重策略
根据题目定义,这边未给出明确的方法
i: vi 
k: vk
j: vj
*/
int w(int i, int k, int j){
	return 0;	
}

构造最优剖分:

s[i][j] 记录着与 v i − 1 v_{i-1} vi1 v i v_{i} vi 一起构成三角形的第三个顶点位置,即切分点。寻找最优剖分可以类似矩阵连乘中寻找最优结合的方法,即找到剖点后依次向两边递归即可。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值