大家好,我是连人,本期接着说动态规划的问题。
这是一个凸多边形。对于这个凸多边形,我们可以将弦连接,将其分为多个三角形。
那么问题来了,怎么做才能使这些三角形的权值之和最小呢?
在这里,权值可以是任何和弦长,边长有关的权函数,一般来说,我们使用三角形的边长作为权值。
在这个问题中,是具有最优子结构的。
设一共有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也打印出来了,给大家一定参考:
转载注明出处。