火车票余票问题的算法解析(续)
作者:互联网
作者: Phill King
邮箱: phillking1982@163.com
原创文章,转载请注明出处。
在之前的文章中,我分析了火车票余票的问题,提供了一个搞笑的算法。在本文中,我们继续讨论无座位号的余票计算以及逐票更新的问题。 之前的分析参见: https://blog.csdn.net/jinij/article/details/87971283
无座位号余票计算
还是以站点数=6, 座位=5为例
如果不考虑座位号,我们只需要考虑每站售出的票数即可。
(1-2)的余票数即为 总票数减去售票数 5 - 2 = 3
(2-3)的余票数即为 总票数减去售票数 5 - 3= 2
以此类推
(1-3)的余票数即为 总票数减去 (1-2)和(2-3)售票数较大者 即 5- max(2,3) = 2
(2-4)的余票数即为 总票数减去 (2-3)和(3-4)售票数较大者 即 5- max(3,4) = 1
以此类推
计算余票的公式
设定 Ti 代表从i站到i+1站的售票数, 如T1 = 2, T2=3
以T(i,j)表示从 i站到j站的售票数
T(i,j) = 总票数 - max(Ti, Ti+1, ... Tj-1)
同理,如果用Ri代表从i站到i+1站的余票数
以R(i,j)表示从 i站到j站的售票数
R(i,j) = min(Ri, Ri+1, ... Rj-1)
对应的余票表:
只需要计算和保存每个站点段的余票数,就可以更新任意两个站点的余票数或整张余票表。
由此可以看出无座位号的余票计算方式更简单更快。
逐票更新
如果想要每购买一张票之后就更新余票表,即无需更新整张表,而只需更新受到影响的部分站点。
无座位号逐票更新
我们看一下无座位号逐票更新的例子。(行表头是起点站, 列表头是到达站)
假设每站总票数为10,现在购买了3-4站的一张车票,那么更新的范围是其右上方的矩形。
影响的范围对于(i,i+1)站段来说是: 行从0到i, 列从i+1到终点站的矩形范围。
如果再购买一张4-5的票,新的余票表如下:
在更新余票的时候我们逐个比较余票的值,
如果余票本来的值比新的值大,则更新为新的值;
如果余票本来的值已经小于新的值,则无需更新。
以购买一张3-4站,然后购买一张3-5站为例
有座位号的逐票更新
有座位号的逐票更新余票逻辑相对简单,只需要把更新范围内的集合都更新一遍即可。
以购买一张3-4站车票为例:
将影响范围内的集合都更新一遍,如果该座位已被包含,可以跳过之后的座位更新。(具体细节不做累述)
同样采用位图法,可以获得很好的性能。
总结
本文对火车票余票问题的无座位号余票更新和逐票更新的情况做了详细的分析。
逐票更新的性能超过更新整张表,但是如果对每张票都做更新总体上需要消耗更多的资源和时间。
具体要视实际需求而定。
相关的代码可以在之前的文章内找到
标签:售票,余票,票数,更新,算法,逐票,座位号,火车票 来源: https://blog.csdn.net/jinij/article/details/88030591