当前位置: 首页 > news >正文

12306 出票算法随想(二)

在原文《12306出票算法随想(一)》基础上,将递归改为了迭代算法,然后加了个简单的锁而已。


using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Threading;namespace Ticket {public static class Program {public static void Main() {var train = new Train(100);var line = new Line(new List<Station> {new Station("A", TimeSpan.Parse("1:00"), TimeSpan.Parse("1:00")),new Station("B", TimeSpan.Parse("2:00"), TimeSpan.Parse("2:05")),new Station("C", TimeSpan.Parse("3:00"), TimeSpan.Parse("3:10")),new Station("D", TimeSpan.Parse("4:00"), TimeSpan.Parse("4:06")),new Station("E", TimeSpan.Parse("5:00"), TimeSpan.Parse("5:00"))});var booking = new Booking(line, train);var watcher = new Watcher(booking);Console.Write("Line route[interval]: ");foreach (var station in booking.Line.Stations)Console.Write($"{station.Name} -> ");Console.WriteLine($"[{booking.Intervals.Count}]");try {booking.Sell(0, 1, 36);booking.Sell(0, 2, 4);booking.Sell(0, 3, 6);booking.Sell(0, 4, 32);booking.Sell(1, 2, 27);booking.Sell(1, 4, 11);booking.Sell(3, 4, 12);Console.WriteLine("Sold at this moment:");Console.WriteLine(booking.ToString());Console.WriteLine("Available at this moment:");foreach (var interval in booking.Intervals) {Console.Write(" {0}{1}[{2}]",booking.Line.Stations[interval.Item1].Name,booking.Line.Stations[interval.Item2].Name,booking.Available(interval.Item1, interval.Item2));}Console.WriteLine();watcher.RunTrain();}catch (ArgumentOutOfRangeException e) {Console.WriteLine(e.Message);}}}internal class Station {public Station(string name, TimeSpan arrival, TimeSpan depart) {Contract.Requires(arrival <= depart);Name = name;Arrival = arrival;Depart = depart;}public string Name { get; }public TimeSpan Arrival { get; }public TimeSpan Depart { get; }public bool Before(Station that) => Depart < that.Arrival;public bool After(Station that) => Arrival > that.Depart;}internal class Line {public Line(IList<Station> stations) {Contract.Requires(stations.Count >= 2);Stations = stations;}public IList<Station> Stations { get; }}internal class Train {private readonly object _lock = new object();private int _load;public Train(int capacity) {Contract.Requires(capacity > 0);Capacity = capacity;_load = 0;}public int Capacity { get; }public int Load {get {lock (_lock) {return _load;}}}public int Board(int amount) {lock (_lock) {_load += amount;if (_load > Capacity)throw new ArgumentOutOfRangeException(nameof(amount), "Train is overloading.");return amount;}}public int Land(int amount) {lock (_lock) {_load -= amount;if (_load < 0)throw new ArgumentOutOfRangeException(nameof(amount), "Train loading should not be negative.");return amount;}}}internal class Booking {public Line Line { get; }public Train Train { get; }public IList<Tuple<int, int>> Intervals { get; } = new List<Tuple<int, int>>();private ConcurrentDictionary<Tuple<int, int>, int> Sold { get; } = new ConcurrentDictionary<Tuple<int, int>, int>();private readonly object _lock = new object();private int[] _loadingCache;private int[] _beginWithCache;private int[] _endWithCache;public Booking(Line line, Train train) {Line = line;Train = train;GenerateIntervals();ResetSold();_loadingCache = new int[Line.Stations.Count];_beginWithCache = new int[Line.Stations.Count];_endWithCache = new int[Line.Stations.Count];UpdateLoadingCache();}public void Sell(int begin, int end, int amount) {Contract.Requires(begin < end);Contract.Requires(amount > 0);var key = new Tuple<int, int>(begin, end);Sold.AddOrUpdate(key, amount, (k, v) => v + amount);lock (_lock) {UpdateLoadingCache();}}public int BeginWith(int station) {return _beginWithCache[station];}public int EndWith(int station) {return _endWithCache[station];}private void UpdateLoadingCache() {if (_loadingCache == null || _loadingCache.Length != Line.Stations.Count) {_loadingCache = new int[Line.Stations.Count];_beginWithCache = new int[Line.Stations.Count];_endWithCache = new int[Line.Stations.Count];}// 预计算每个站点的上车和下车人数Array.Clear(_beginWithCache, 0, _beginWithCache.Length);Array.Clear(_endWithCache, 0, _endWithCache.Length);foreach (var kvp in Sold) {var interval = kvp.Key;var amount = kvp.Value;_beginWithCache[interval.Item1] += amount;_endWithCache[interval.Item2] += amount;}// 计算每个站点的负载_loadingCache[0] = _beginWithCache[0];for (var station = 1; station < Line.Stations.Count; station++) {_loadingCache[station] = _loadingCache[station - 1] - _endWithCache[station] + _beginWithCache[station];}}private int LoadingAt(int station) {return _loadingCache[station];}public int Available(int begin, int end) {Contract.Requires(begin < end);var maxloading = 0;for (var station = begin; station < end; station++)maxloading = Math.Max(maxloading, LoadingAt(station));return Train.Capacity - maxloading;}private void GenerateIntervals() {Intervals.Clear();for (var begin = 0; begin < Line.Stations.Count - 1; begin++) {for (var end = begin + 1; end < Line.Stations.Count; end++)Intervals.Add(new Tuple<int, int>(begin, end));}}private void ResetSold() {Sold.Clear();foreach (var interval in Intervals)Sold.TryAdd(interval, 0);lock (_lock) {UpdateLoadingCache();}}public override string ToString() {return Intervals.Aggregate(string.Empty, (current, interval) =>current +$" {Line.Stations[interval.Item1].Name}{Line.Stations[interval.Item2].Name}[{Sold.GetOrAdd(interval, 0)}]");}}internal class Watcher {public Watcher(Booking booking) {Booking = booking;}private Booking Booking { get; }public void RunTrain() {for (var station = 0; station < Booking.Line.Stations.Count; station++) {Console.Write("Train arrived [{0}]:", Booking.Line.Stations[station].Name);Console.WriteLine("  -{0,3},   +{1,3} = {2}",Booking.Train.Land(Booking.EndWith(station)),Booking.Train.Board(Booking.BeginWith(station)),Booking.Train.Load);}}}
}
http://www.rkmt.cn/news/73815.html

相关文章:

  • 代码随想录Day29_贪心3
  • 订单流程服务(OrderProcessor)
  • 跨平台移动端
  • 7.订单流程服务(OrderProcessor)
  • 实验5作业
  • 第46天(中等题 数据结构)
  • # Linus Torvalds vs. 模糊抽象:代码命名清晰性与认知负荷的工程思维
  • # MVP架构选型指南:停止过度设计,从简单开始
  • C++学习备忘:深度解构 C++ 智能指针
  • # 结构化拖延批判性分析:John Perry案例
  • 主流AI编程工具横向对比与选型指南【From DeepSeek-V3】
  • # LinkedIn代码重构失败案例:300万行代码的迁移困境与组织文化反思
  • # HyDE论文解读:零样本密集检索的巧思(2022)
  • Scalar使用说明
  • 最新版Flutter3.38+Dart3.10仿写抖音APP直播+短视频+聊天应用程序
  • eshop订单状态流转详解
  • 用 TensorFlow 构建深度学习验证码识别系统
  • 20251205 之所思 - 人生如梦
  • git洁癖:如果冲突采用远端
  • 快捷键
  • 日总结 36
  • 使用fail2ban屏蔽LINUX恶意暴力破解密码
  • 对接墨西哥股票市场 k线图表数据klinechart 数据源API
  • 10412_基于Springboot的员工绩效管理系统
  • NFL如何用统一数据平台提升比赛与体验
  • 每日反思(2025年12月5日)
  • 如何将 iPhone 或 iPad 备份移至外置硬盘
  • Linux指定端口连接Redis
  • Linux 分页显示
  • 春招准备之MyBatis框架篇 - 详解