TrianglePath 三角形路径

问题

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

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

解法

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

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

三角形的第nn行有nn个节点,因此节点ii的左下节点(类似于左孩子节点)为i+ni + n,右下节点为i+n+1i + n + 1。节点ii的左上节点为in2i-n-2,右上节点为in1i-n-1。根据节点下标ii如何计算其属于第几行呢?因为n×(n1)2+1i(n+1)×n2\frac{n \times (n-1)}{2} + 1 \leq i \leq \frac{(n+1) \times n}{2},可以先粗略的估算n=2×in = \lfloor \sqrt{2 \times i} \rfloor,然后判断节点ii是否处于第nn行中。

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

f(i)={v1(initialize)i=1min(f(iheight(i)2),f(iheight(i)1))+vi(loop)i[2,k]f(i) = \begin{cases} v_{1} & (initialize) & i = 1 \\ min(f(i-height(i)-2), f(i-height(i)-1)) + v_{i} & (loop) & i \in [2,k] \end{cases}

(1)(1) 初始化,节点1到它自己的代价为f(1)=v1f(1) = v_{1}

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

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

LeetCode

leetcode-120.cpp

源码

TrianglePath.h

TrianglePath.cpp

测试

TrianglePathTest.cpp

Last updated