动态规划:凸多边形最优三角剖分

大家好,我是连人,本期接着说动态规划的问题。
在这里插入图片描述
这是一个凸多边形。对于这个凸多边形,我们可以将弦连接,将其分为多个三角形。
在这里插入图片描述
那么问题来了,怎么做才能使这些三角形的权值之和最小呢?

在这里,权值可以是任何和弦长,边长有关的权函数,一般来说,我们使用三角形的边长作为权值。

在这个问题中,是具有最优子结构的。

设一共有n边的凸多边形点的集合为{v0,v1,… ,vn-1},在以v0和vn-1为底的情况下,求k∈(0,n-1),使v0,vn-1,vk组成的三角形权值最小。

这样,剩下的两个点集{v0,…,vk}和{vk,…,vn-1}就可以组成新的凸多边形。
在这里插入图片描述

在其中,定义一个二维数组t[ i ][ j ],它的含义是在凸多边形{vi-1,vi,…,vj}的最优三角剖分的权值(以vi-1,vj为底,寻找k∈[i,j]的第三个顶点,使权值最小。这样说可能更容易理解),以i来代替i-1可以避开两个点被判定为三角形的情况所造成的麻烦。因此可得递归式:
在这里插入图片描述

这个式子跟矩阵连乘问题还是非常相似的,因此我们再定义一个二维数组s,负责记录在凸多边形{vi-1,vi,…,vj}中的第三顶点k。

同样地,t和s只使用右上部分,对角线为0,剩下的以如下顺序记录:
在这里插入图片描述
这个图有点问题,因为第0行是不使用的,因为不可能有第-1个点给0当底。

作为例子的多边形是我在网上档的,因为看见好几篇都用的这个例子也无法找到原出处了。

weight = [
    [0, 2, 2, 3, 1, 4],
    [2, 0, 1, 5, 2, 3],
    [2, 1, 0, 2, 1, 4],
    [3, 5, 2, 0, 6, 2],
    [1, 2, 1, 6, 0, 1],
    [4, 3, 4, 2, 1, 0]
]


def w(a, b, c):
    global weight
    return weight[a][b] + weight[b][c] + weight[a][c]


def min_weight_triangulation(t, s, n):
    for r in range(1, n - 1):
        for i in range(1, n - r):
            j = i + r
            t[i][j] = t[i + 1][j] + w(i - 1, i, j)
            s[i][j] = i
            for k in range(i + 1, j):
                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
    return t[1][n-1]


def traceback(i, j, s):
    if i == j:
        return
    traceback(i, s[i][j], s)
    traceback(s[i][j] + 1, j, s)
    print(str(i - 1) + ' ' + str(j) + ' ' + str(s[i][j]))


if __name__ == '__main__':
    n = 6
    t = []
    s = []
    for i in range(0, n):
        t.append([])
        s.append([])
        for j in range(0, n):
            t[i].append(0)
            s[i].append(0)
    print("最优剖分权值:" + str(min_weight_triangulation(t, s, n)))
    traceback(1, 5, s)

如下是运行结果,我将t和s也打印出来了,给大家一定参考:
在这里插入图片描述
转载注明出处。

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值