动态规划进阶问题:二维矩阵最大幸福值路径求解
嘿,这个动态规划的问题卡在这里很正常,核心难点就是连续左移的扣减计数会影响后续的幸福值计算,原来只记录(i,j)位置的最大幸福值肯定不够,得把连续左移的状态也加进DP里才行!我给你一步步拆解:
1. 重新设计DP状态
我们需要把「连续左移的次数」作为状态的一部分,这样才能准确计算扣减:
定义 dp[i][j][k] 表示:
- 到达单元格
(i,j)时,最后一步是连续第k次左移(k=0表示最后一步是向下移动,或者刚跳到这一行还没左移) - 存储的值是该状态下能获得的最大幸福值
2. 基础情况初始化
- 起点是右上角
(0, m-1),此时没有任何移动,连续左移次数为0,所以dp[0][m-1][0] = Happiness[0][m-1] - 根据规则1,我们可以直接跳过任意行到某一行的最右列(
j=m-1),所以所有dp[i][m-1][0]都可以初始化为Happiness[i][m-1](相当于直接从起点跳过来) - 其他所有状态先初始化为负无穷,表示暂时不可达
3. 状态转移逻辑
我们按列从右到左遍历(因为向左移动依赖右侧列的状态),行可以从上到下遍历,分两种转移情况:
情况1:从上方(或任意上一行)向下移动到 (i,j)
此时到达 (i,j) 后,连续左移次数重置为0,我们需要取所有上一行(包括跳过多行的情况)的最大幸福值加上当前单元格的幸福值:
# 可以维护一个row_max数组,记录每列j目前为止的最大幸福值,优化跳过任意行的计算 row_max[j] = max(row_max[j], max(dp[i-1][j][k] for k in range(max_possible_k))) dp[i][j][0] = row_max[j] + Happiness[i][j]
如果不想维护row_max,也可以直接遍历所有 x < i 的行,取 dp[x][j][*] 的最大值,只是效率稍低。
情况2:从右侧 (i,j+1) 向左移动到 (i,j)
这里要根据右侧状态的连续左移次数计算扣减:
- 如果右侧状态是
k_prev=0(最后一步是向下):这次是首次左移,扣减1,当前连续左移次数变为1dp[i][j][1] = max(dp[i][j][1], dp[i][j+1][0] + Happiness[i][j] - 1) - 如果右侧状态是
k_prev>=1(已经连续左移了k_prev次):这次是第k_prev+1次左移,扣减k_prev+1,当前连续左移次数变为k_prev+1dp[i][j][k_prev+1] = max(dp[i][j][k_prev+1], dp[i][j+1][k_prev] + Happiness[i][j] - (k_prev+1))
4. 最终结果
终点是左下角 (n-1, 0),我们只需要取这个位置所有可能的连续左移次数对应的最大幸福值:
max_happiness = max(dp[n-1][0][k] for k in range(max_possible_k))
举个小例子验证
比如一个3x3的幸福矩阵:
Happiness = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]
- 初始化所有
dp[i][2][0]为对应值:dp[0][2][0]=3,dp[1][2][0]=6,dp[2][2][0]=9 - 向下转移到
(1,2):dp[1][2][0] = max(3+6,6)=9;向下到(2,2):dp[2][2][0] = max(9+9,9)=18 - 向左到
(2,1):dp[2][1][1] = 18 +8 -1=25 - 向左到
(2,0):dp[2][0][2] =25 +7 -2=30 - 最终最大值就是30,符合预期
这样设计状态后,就能完美跟踪连续左移的扣减次数,找到最优路径啦!
内容的提问来源于stack exchange,提问作者forfun
相关产品推荐
相关产品推荐

