切呀切披萨——最优三角剖分

来源:互联网 发布:java 设置文件权限 编辑:程序博客网 时间:2024/06/07 00:27
切呀切披萨——最优三角剖分
本文来自本人著作《趣学算法》,在线章节http://www.epubit.com.cn/book/details/4825

有一块多边形的披萨,上面有各种各样的好吃的,我们希望沿着两个不相邻的两个顶点切成小三角形,尽可能少的切碎披萨上面的蔬菜、肉片。

 

 

 

4-53美味披萨

 

  1. 问题分析

我们可以把披萨饼看作一个凸多边形,什么是凸多边形呢,就是多边形的任意两点的连线在均落在多边形的内部或边界上。

1.什么是凸多边形?

例如图4-54是一个凸多边形,图4-55不是凸多边形,因为v1v3的连线落在了多边形的外部。


凸多边形不相邻的两个顶点的连线称为凸多边形的弦。

2.什么是凸多边形三角剖分?

凸多边形的三角剖分是指将一个凸多边形分割成互不相交的三角形的弦的集合。例如图4-56的一个三角剖分是{ v0v4v1v3v1v4},另一个三角剖分是{ v0v2v0v3v0v4},一个凸多边形的三角剖分有很多种。


如果我们给定凸多边形及定义在边、弦上的权值,即任意两点之间定义一个数值作为权值。如图4-57所示。


三角形上权值之和是指三角形的三条边上权值之和:


3.什么是凸多边形最优三角剖分?

一个凸多边形的三角剖分有很多种,最优三角剖分就是划分的各三角形上权函数之和最小的三角剖分。

再回到切披萨的问题上来,我们可以把披萨看作一个凸多边形,任何两个顶点的连线对应的权值代表上面的蔬菜肉片数,我们希望沿着两个不相邻的两个顶点切成小三角形,尽可能少的切碎披萨上面的蔬菜、肉片。那么,该问题可以归结为凸多边形的最优三角剖分问题。

假设把披萨看作一个凸多边形,把各顶点标注出来,{v0v1,…,vn}。那么怎么得到它的最优三角剖分呢?

首先分析该问题是否具有最优子结构性质:

1.分析最优解的结构特征。

假设已经知道了在第k个顶点切开会得到最优解,那么原问题就变成了了两个子问题和一个三角形,子问题分别是:{v0v1,…,vk}{vkvk+1,…,vn},三角形为v0vkvn


那么原问题的最优解是否包含子问题的最优解呢?

证明:假设{v0v1,…,vn}三角剖分的权值之和是c{v0v1,…,vk}三角剖分的权值之和是a{vkvk+1,…,vn}三角剖分的权函数之和是b,三角形v0vkvn的权值之和是w(v0vkvn),那么c=a+b+ w(v0vkvn),因此我们只需要证明如果c是最优的,则ab一定是最优的(即原问题的最优解包含子问题的最优解)。反证法:如果a不是最优的,{v0v1,…,vk}三角剖分一定存在一个最优解aˊaˊ<a,那么aˊ+b+w(v0vkvn)<c,所以c不是最优的,这与假设c是最优的矛盾,因此如果c是最优的,则a一定是最优的。同理可证b也是最优的。因此如果c是最优的,则ab一定是最优的。

因此,凸多边形的最优三角剖分问题具有最优子结构性质。

2.建立最优值的递归式。

m[i][j]表示凸多边形{vi-1vi,…,vj}三角剖分的最优值,那么两个子问题:{vi-1vi,…,vk}{vkvk+1,…,vj}对应的最优值分别是m[i][k]m[k+1][j]。剩下的就是三角形vi-1vkvj的权值之和是w(vi-1vkvj)


i=j时,{vi-1vi,…,vj}就变成了{vi-1vi }是一条线段,不能形成一个三角形剖分,我们可以将其看作退化的多边形,其权值设置为0

凸多边形三角剖分最优解递归式:


3.自底向上计算最优值,并记录。

先求只有三个顶点凸多边形三角剖分的最优值,再求四个顶点凸多边形三角剖分的最优值,…,一直到n个顶点凸多边形三角剖分的最优值。

4.构造最优解。

上面得到的最优只是凸多边形三角剖分的三角形权值之和最小值,并不知道是怎样剖分的,我们需要从记录表中还原剖分次序,找到最优剖分的弦,由这些弦构造出最优解。

如图4-61所示,如果vk能够得到凸多边形{vi-1vi,…,vj}的最优三角剖分,那么我们就找到两条弦vi-1vkvkvj,把这两条弦放在最优解集合里面,继续求解两个子问题最优三角剖分的弦。


凸多边形最优三角剖分的问题,首先判断该问题是否具有最优子结构性质,有了这个性质就可以使用动态规划,然后分析问题找最优解的递归式,根据递归式自底向上求解,最后根据最优决策表格,构造出最优解。

算法设计

凸多边形最优三角剖分满足动态规划的最优子结构性质,可以从自底向上逐渐推出整体的最优。

  1. 首先确定合适的数据结构。采用二维数组g[][]来记录各个顶点之间的连接权值。二维数组m[][]来存放各个子问题的最优值,二维数组s[][]来存放各个子问题的最优决策。
  2. 初始化。输入顶点数n,然后依次输入各个顶点之间的连接权值存储在二维数组g[][]中,令n=n-1(顶点标号从v0开始)m[i][i]=0s[i][i]=0,其中i= 1,2,3,...,n
  3. 循环阶段:
    1. 按照递归关系式计算3个顶点{vi-1vivi+1}的最优三角剖分,j=i+1,将最优值存入m[i][j],同时将最优策略记入s[i][ j]i=1,2,3,...,n -1
    2. 按照递归关系式计算4个顶点{vi-1vivi+1vi+2}的最优三角剖分,j=i+2,将最优值存入m[i][ j],同时将最优策略记入s[i][ j]i=1,2,3,...,n -2
    3. 以此类推,.....,直到求出所有顶点 {v0v1...vn}的最优三角剖分,并将最优值存入m [1][n],将最优策略记入s[1][n]
  4. 构造最优解

    根据最优决策信息数组s[][]递归构造最优解,即输出凸多边形最优剖分的所有弦。s[1][n]表示凸多边形{v0v1...vn}的最优三角剖分位置,如图4-62所示:


  1. 如果子问题1为空,即没有一个顶点,说明v0 vs[1][n]是一条边,不是弦,不需输出,否则,输出该弦v0vs[1][n]
  2. 如果子问题2为空,即没有一个顶点,说明vs[1][n] vn是一条边,不是弦,不需输出,否则,输出该弦vs[1][n]vn
  3. 递归构造两个子问题{v0v1...v s[1][n]}{vs[1][n]v1...vn},一直递归到子问题为空停止。
完美图解、伪码详解、实战演练、优化拓展,详见《趣学算法》第4章。
阅读全文
0 0
原创粉丝点击