如何在Racket中实现两种合约的短信收支平衡点计算函数
指导思路:实现合约收支平衡点函数
听起来你已经把基础工作做得相当扎实了——合约结构体、总成本计算函数contract-total和价格比较函数cheaper?都已经到位,接下来找收支平衡点的思路可以拆解成几个清晰的步骤,我给你梳理下方向:
1. 先明确核心目标
我们要找的是最小的短信条数n,使得从n条短信开始,其中一份合约的总成本超过另一份;如果无论发送多少条短信,总有一份合约始终更便宜,就返回false。
2. 从初始状态入手分析
先检查sms=0时的成本情况:
- 如果两份合约成本相等:那需要找第一个让它们成本拉开差距的短信条数;
- 如果一开始
ctr1就比ctr2便宜:我们要找最小的n,使得ctr2的总成本首次低于ctr1(反之亦然); - 如果初始状态下,其中一份合约的成本增长速度(也就是超出免费短信后的每条短信成本)始终比另一份慢,那它会一直更便宜,直接返回
false。
3. 利用成本函数的分段线性特性
每个合约的总成本是分段线性函数,分界点就是它的freesms(免费短信条数)。所以我们可以把短信数量的范围分成几个关键区间,在每个区间内,两个合约的总成本都是线性的,更容易计算交点:
- 区间1:
0 ≤ sms ≤ min(freesms1, freesms2)——此时两份合约都在免费短信额度内,总成本都是固定值(基础费+两年月费); - 区间2:
min(freesms1, freesms2) < sms ≤ max(freesms1, freesms2)——此时其中一份合约开始按条收费,另一份还在免费额度内; - 区间3:
sms > max(freesms1, freesms2)——两份合约都超出免费额度,总成本都是“固定成本 + 超出部分短信费”的线性函数。
4. 逐个区间检查交点
对每个区间,我们可以先写出两份合约在该区间内的成本表达式(线性形式:斜率*sms + 截距),然后解方程找交点:
举个区间内的计算例子
假设在区间[low, high]内:
ctr1的成本表达式:m1*sms + b1(m1是超出免费后的每条短信费,没超出的话m1=0;b1是固定成本:基础费+两年月费)ctr2的成本表达式:m2*sms + b2
然后:
- 如果
m1 == m2:两个函数平行,要么成本始终相等,要么差距固定,这个区间内没有平衡点; - 如果
m1 != m2:解方程m1*sms + b1 = m2*sms + b2,得到sms = (b2 - b1)/(m1 - m2);- 若这个
sms值落在当前区间[low, high]内,且是正整数(如果是小数,取大于等于它的最小整数,因为短信条数是整数),那这个数就是我们要找的平衡点——因为在这个点之前,一份更便宜,之后另一份反超; - 找到第一个这样的最小
n就可以返回了。
- 若这个
5. 处理边界情况
别忘了考虑这些特殊场景:
- 其中一个合约没有免费短信(
freesms=0); - 两份合约的
freesms值相同; - 解方程得到的是小数(比如150.3,那151条短信才会触发价格反转);
- 所有区间都找不到交点(说明一份合约始终更便宜),此时返回
false。
6. 可以先写辅助函数
你可以先实现一个小的辅助函数,比如find-interval-crossing,输入两个线性函数的斜率、截距,以及区间的上下限,返回该区间内是否存在平衡点,以及对应的短信条数。这样主函数只需要遍历三个区间,调用辅助函数即可。
内容的提问来源于stack exchange,提问作者J. Hatic
相关产品推荐
相关产品推荐

