Maximum Tip Calculator递归解法问题:测试用例输出不符排查
Maximum Tip Calculator 递归解法错误分析与修正
首先,我们先拆解你的问题:你基于0-1背包思路实现了朴素递归解法,但在一个看似不符合题目前提(X+Y<N)的测试用例中输出错误,正确结果为110,你的代码输出106。下面我们一步步分析问题所在:
问题核心:递归边界条件处理不当
题目明确要求必须处理完所有N个订单,且保证X+Y≥N(不存在无法分配的情况)。你的测试用例中X=3、Y=3、N=7,X+Y=6<7,其实不符合题目给定的前提,但既然正确输出是110,推测可能是测试用例的X/Y值存在笔误(比如Y应为4)。不过无论如何,你的代码输出错误的根源在于递归边界条件的缺失。
正确的递归逻辑应该包含的边界条件
朴素递归的核心是对每个订单做两种选择,但必须处理两种极端情况:
- 当所有订单处理完成(
i == N),返回0; - 当Rahul的额度用尽(
x == 0),剩余所有订单必须由Ankit承接,直接返回剩余B数组的总和(题目保证Y≥剩余订单数); - 当Ankit的额度用尽(
y == 0),剩余所有订单必须由Rahul承接,直接返回剩余A数组的总和。
如果你的代码没有处理上述第2、3条边界,而是继续尝试两种选择(其中一种已不可行),就会导致:
- 在符合题目前提的场景下,错过最优分配方式;
- 在X+Y<N的异常场景下,放弃部分订单,导致总和偏低(比如你的测试用例中少计算了部分订单的小费)。
修正后的递归思路
以你的测试用例(假设Y=4,符合X+Y≥N)为例,正确的分配方式是:
- Rahul承接订单0(8)、3(19)、6(18),总和
8+19+18=45; - Ankit承接订单1(7)、2(15)、4(12)、5(31),总和
7+15+12+31=65; - 总小费
45+65=110,与正确输出一致。
修正后的递归伪代码如下:
def max_tip(i, x, y, A, B): # 边界1:所有订单处理完成 if i == len(A): return 0 # 边界2:Rahul无额度,剩余全由Ankit承接 if x == 0: return sum(B[i:]) # 边界3:Ankit无额度,剩余全由Rahul承接 if y == 0: return sum(A[i:]) # 两种选择取最大值 choose_rahul = A[i] + max_tip(i+1, x-1, y, A, B) choose_ankit = B[i] + max_tip(i+1, x, y-1, A, B) return max(choose_rahul, choose_ankit)
额外优化:加入记忆化避免重复计算
朴素递归会存在大量重复子问题,导致效率低下。可以通过三维数组或字典存储已计算过的dp[i][x][y]结果,避免重复计算:
def max_tip_memo(i, x, y, A, B, memo): if i == len(A): return 0 if (i, x, y) in memo: return memo[(i, x, y)] if x == 0: res = sum(B[i:]) elif y == 0: res = sum(A[i:]) else: choose_rahul = A[i] + max_tip_memo(i+1, x-1, y, A, B, memo) choose_ankit = B[i] + max_tip_memo(i+1, x, y-1, A, B, memo) res = max(choose_rahul, choose_ankit) memo[(i, x, y)] = res return res
总结
你的代码输出错误的根本原因是未处理额度用尽时的边界情况,导致无法强制分配剩余订单,进而错过最优解或遗漏部分订单。修正边界条件后,即可得到正确结果。同时,加入记忆化可以大幅提升递归解法的效率。
内容的提问来源于stack exchange,提问作者TTT
相关产品推荐
相关产品推荐

