从一道PTA算法题看C++实战:如何用结构体+Map模拟口罩发放系统(附完整代码)

张开发
2026/5/3 10:34:16 15 分钟阅读
从一道PTA算法题看C++实战:如何用结构体+Map模拟口罩发放系统(附完整代码)
从零构建口罩发放系统C结构体与STL的工程实践在软件开发领域将现实业务需求转化为高效可靠的代码实现是每个程序员必须掌握的核心能力。今天我们就以一个实际的口罩发放系统为例探讨如何运用C的结构体和标准模板库(STL)来构建一个完整的解决方案。1. 需求分析与系统设计任何优秀的代码实现都始于对需求的透彻理解。让我们先拆解这个口罩发放系统的核心业务规则用户信息验证身份证号必须是18位纯数字发放频率控制成功领取后需间隔P天才能再次申请优先级排序按提交时间先后顺序发放时间相同则按录入顺序特殊人群记录需单独记录身体状况异常的申请人面对这样的需求我们需要设计合理的数据结构来高效处理这些业务逻辑。结构体(Struct)非常适合用来封装用户的多维属性而STL中的map容器则能帮助我们快速查找和更新用户状态。struct Applicant { string name; string id; int health_status; // 0健康 1有症状 int apply_hour; int apply_minute; int last_issued_day -1; // 上次发放日期-1表示从未发放 int sequence; // 录入顺序 };2. 核心数据结构实现2.1 用户信息管理我们使用map来存储所有合法用户的信息以身份证号作为keymapstring, Applicant all_applicants;这种设计带来几个显著优势O(log n)时间复杂度的查找效率自动去重确保同一身份证号只有一条记录方便更新用户的最新状态2.2 每日申请处理每天的处理流程可以分为几个关键步骤数据录入与过滤读取当日申请过滤掉身份证不合法的记录优先级排序按时间先后和录入顺序排序名额分配按排序结果发放口罩考虑间隔限制特殊人群记录标记身体状况异常的申请人vectorApplicant daily_applications; // 存储当日合法申请 // 示例身份证验证函数 bool isValidID(const string id) { if(id.length() ! 18) return false; return all_of(id.begin(), id.end(), ::isdigit); }3. 关键算法实现细节3.1 排序算法定制系统要求按申请时间排序时间相同则按录入顺序。我们可以自定义比较函数bool compareApplicants(const Applicant a, const Applicant b) { if(a.apply_hour ! b.apply_hour) return a.apply_hour b.apply_hour; if(a.apply_minute ! b.apply_minute) return a.apply_minute b.apply_minute; return a.sequence b.sequence; } // 使用示例 sort(daily_applications.begin(), daily_applications.end(), compareApplicants);3.2 发放逻辑实现口罩发放需要考虑用户的上次领取时间for(const auto app : daily_applications) { if(issued_count daily_quota) break; auto user all_applicants[app.id]; if(user.last_issued_day -1 || current_day - user.last_issued_day P) { cout user.name user.id endl; user.last_issued_day current_day; issued_count; } }4. 系统扩展与优化思路4.1 性能优化建议当处理大规模数据时可以考虑以下优化使用unordered_map替代map将查找复杂度降至O(1)预分配vector空间避免频繁内存分配多线程处理不同日期的数据4.2 业务功能扩展实际生产环境中系统可能需要更多功能发放记录持久化存储数据统计与分析报表异常申请检测机制用户通知系统集成// 示例扩展数据结构支持新功能 struct EnhancedApplicant : Applicant { vectorint issue_history; // 发放记录 string contact; // 联系方式 int total_issued 0; // 累计发放数量 };5. 完整代码实现与测试以下是整合各模块后的完整实现#include iostream #include vector #include map #include algorithm using namespace std; struct Applicant { string name; string id; int health; int hour, minute; int sequence; int last_issued -1; }; bool isValidID(const string id) { return id.length() 18 all_of(id.begin(), id.end(), ::isdigit); } bool compareApps(const Applicant a, const Applicant b) { if(a.hour ! b.hour) return a.hour b.hour; if(a.minute ! b.minute) return a.minute b.minute; return a.sequence b.sequence; } int main() { int D, P; cin D P; mapstring, Applicant all_apps; mapstring, bool health_concerns; for(int day 1; day D; day) { int T, S; cin T S; vectorApplicant daily; for(int i 0; i T; i) { Applicant app; char sep; cin app.name app.id app.health app.hour sep app.minute; app.sequence i; if(!isValidID(app.id)) continue; daily.push_back(app); all_apps[app.id] app; if(app.health 1) { health_concerns[app.id] true; } } sort(daily.begin(), daily.end(), compareApps); int issued 0; for(const auto app : daily) { if(issued S) break; auto user all_apps[app.id]; if(user.last_issued -1 || day - user.last_issued P) { cout user.name user.id endl; user.last_issued day; issued; } } } for(const auto [id, _] : health_concerns) { cout all_apps[id].name id endl; } return 0; }6. 常见问题与调试技巧在实现这类系统时开发者常会遇到几个典型问题时间比较错误确保正确解析和比较hh:mm格式的时间边界条件处理特别注意第一天和最后一天的发放逻辑状态更新遗漏发放后务必更新last_issued_day性能瓶颈大规模数据时注意选择合适的数据结构调试时可以采用的策略添加详细日志输出关键变量状态编写单元测试验证排序和发放逻辑使用小规模测试数据逐步验证7. 类似系统的设计模式口罩发放系统的设计模式可以推广到许多类似场景预约系统医院挂号、餐厅订位资源分配系统会议室预订、共享设备管理限购系统电商促销商品购买限制这些系统的共同特点是需要管理有限的资源有资格或优先级规则需要防止滥用或过度使用// 通用预约系统框架示例 templatetypename Resource, typename User class ReservationSystem { mapUser, int last_reserved; int cooldown_period; public: bool make_reservation(const User user, int current_day) { if(last_reserved.count(user) current_day - last_reserved[user] cooldown_period) { return false; } last_reserved[user] current_day; return true; } };在实际项目中这种基于结构体和STL容器的设计方法已经被证明是高效可靠的。它不仅代码清晰易于维护而且性能表现优秀能够处理相当大规模的数据。

更多文章