Triangle Path - 三角形路径


问题

在高度为n的三角形上从最上面移动到最下面,三角形上节点i的值为vi,每次移动只能向下移动左右两个邻节点。从上面移动到下面的代价为所有经过节点的值之和。如图所示:

TrianglePath1.png

给定三角形上的k个节点,求从上到下的最小移动代价。

解法

高度为n的三角形拥有(n+1)×n2个节点。设节点下标从1开始,则第n行的节点为[n×(n1)2+1,,(n+1)×n2]。左边节点为n×(n1)2+1,右边节点为(n+1)×n2

TrianglePath2.png

从上图可知,第1行的节点为[1,1];第2行的节点为[2,3];第3行的节点为[4,6];等等。

三角形的第n行有n个节点,因此节点i的左下节点(类似于左孩子节点)为i+n,右下节点为i+n+1。节点i的左上节点为in2,右上节点为in1。根据节点下标i如何计算其属于第几行呢?因为n×(n1)2+1i(n+1)×n2,可以先粗略的估算n=2×i,然后判断节点i是否处于第n行中。

n=height(i)可以算出节点i的行号,f(i)为到达节点i的最小移动代价(其中i[1,(n+1)×n2])。有状态转移方程:

f(i)={v1(initialize)i=1min(f(iheight(i)2),f(iheight(i)1))+vi(loop)i[2,k]

(1) 初始化,节点1到它自己的代价为f(1)=v1

(2) 对于节点i[2,k],其左上节点为lu=iheight(i)2,右上节点为ru=iheight(i)1。显然只能从左上、右上节点到达i,则到达i的最小代价是这两者中最小的,因此有min(f(iheight(i)2),f(iheight(i)1))+vi

在最后一行中找出最小代价即可。该算法的时间复杂度是O(k2)


LeetCode

leetcode-120.cpp


源码

TrianglePath.h

TrianglePath.cpp

测试

TrianglePathTest.cpp