|
楼主 |
发表于 2024-5-11 23:37
|
显示全部楼层
本帖最后由 shaowu459 于 2024-5-12 00:02 编辑
例题4:
计算从起点前到终点体力值消耗和的最小值。题目描述见下图(不能连续走两个节点的意思是,这次一下走了两个节点,下次只能再走一个节点,不能再一下走两个节点):
在任意一个节点看的时候,有两种状态:一种是下次不能走两个节点,这种情况肯定是前一次是一下走了两个节点;一种是下次能走两个节点,这种情况肯定是从前一个节点走过来的。因此,可以设置dp[ i,1]和dp[ i, 2],dp[ i, 1]代表到下标i且下次不能走两个节点时累计体力消耗最小,dp[ i ,2]代表到下标i且下次能走两个节点时累计体力消耗最小值。下面来具体分析下dp[ i ,1]和d[[2]如何获得。
以到Path7为例,接下来不能走两个节点时体力消耗最小值是Path5的第二种状态消耗体力状态最小值+Path7的体力数值(假设走到这个节点就消耗了当前节点体力值),因为如果在Path7不能走两个节点,只能是从Path5一次性跳两个节点到Path7的。也就是:dp[ i ,1]=dp[i-2][2]+nums
如果在Path7下一次能跳两个节点,说明是从Path6走一个节点过来的,因此,在Path7接下来能走两个节点时体力消耗最小值是前一个节点(Path6)两种状态消费体力的最小值加上当前节点的体力值。也就是:dp[ i ,2]=min(d[i-1][1],dp[i-1][2])+nums
在每个节点情况都是一样的,只不过到第一个节点和第二个节点会稍有问题,我们挨个看一下:
dp[1][1]:
dp[1][2]:
dp[2][1]:
dp[2][2]:
dp[1]和dp[2]都涉及了起始点的值,因此我们可以手动设置一个正确的初始值(根据需要构造),这样,转移状态方程就可以正常推下去了。
结合上面的分析,我们可以写出以下的公式(公式把接下来可走2个节点的结果放在上方,不能走2个节点的结果放在下方):
- =MIN(TAKE(REDUCE({1;1}*A2:B2,C2:V2,LAMBDA(x,y,HSTACK(x,VSTACK(MIN(TAKE(x,,-1)),@TAKE(x,,-2))+N(y)))),,-1))
复制代码
公式中使用{1;1}*A2:B2构造了一个初始值作为REDUCE函数的第一参数,然后遍历数组中的每个元素。在遍历过程中,使用VSTACK函数将当前x中最后一列(前一个节点)的最小值和倒数第二列中第一个值(对应接下来能走两个节点情况)纵向堆积起来,然后再使用HSTACK函数堆积在x右侧。遍历完毕后,提取x最后一列,然后取最小值即可。
|
|