资讯详情

UVa 119题解:模拟礼物交换的算法实现与边界处理

📅 2026/10/26 20:17:00 | 华诺云谱 👁 阅读
UVa 119题解:模拟礼物交换的算法实现与边界处理
1. 问题背景与题目解析UVa 119 Greedy Gift Givers 是UVa Online Judge上的一道经典编程练习题属于初级模拟类题目。这道题最早出现在1996年的USACO训练题库中后来成为许多编程竞赛选手的入门必做题。题目模拟了一个简单的礼物交换场景一群人互相赠送礼物每个人最初有一定金额的钱按照特定规则给其他人赠送礼物后需要计算每个人最终的净金额变化。这类模拟题在编程竞赛中非常常见主要考察选手对问题描述的准确理解、边界条件的处理能力以及基础编程实现技巧。提示虽然题目表面简单但实际提交时通过率不足40%主要问题都出在输入输出格式处理和极端情况考虑上。2. 题目要求详细拆解2.1 输入输出规范输入由多组测试用例组成每组用例包含第一行是整数NP2 ≤ NP ≤ 10表示参与人数接下来NP行每行是一个参与者的名字不超过12个字符然后对于每个参与者按顺序给出赠送者的名字赠送的总金额0 ≤ 金额 ≤ 2000赠送人数NG如果NG 0则后面跟着NG个接收者的名字输出要求对于每个参与者按照输入顺序输出名字 净金额净金额 收到的总金额 - 送出的总金额每组测试用例输出后跟一个空行2.2 核心算法逻辑初始化阶段读取所有参与者姓名建立名字到金额的映射初始金额都设为0处理每个赠送者读取赠送者的名字、总金额和接收者列表计算每人应得金额 总金额 / 接收者人数整数除法赠送者送出金额 每人应得金额 * 接收者人数每个接收者收到相应金额输出阶段按原始顺序计算并输出每个人的净金额2.3 关键边界条件当NG0时不应进行任何金额分配避免除零错误赠送金额为0时无论接收人数多少都不应分配金额名字区分大小写必须精确匹配输出必须严格保持原始输入顺序每组输出后必须有一个空行包括最后一组3. 实现方案与代码解析3.1 数据结构选择最合适的实现方式是使用一个vector或数组保存原始顺序的参与者名字一个unordered_map或map建立名字到净金额的映射一个临时变量保存当前处理者的信息#include iostream #include vector #include unordered_map #include string using namespace std; int main() { int NP; bool first_case true; while (cin NP) { if (!first_case) cout endl; first_case false; vectorstring names(NP); unordered_mapstring, int balance; for (int i 0; i NP; i) { cin names[i]; balance[names[i]] 0; } for (int i 0; i NP; i) { string giver; int amount, NG; cin giver amount NG; if (NG 0) continue; int gift amount / NG; balance[giver] - gift * NG; for (int j 0; j NG; j) { string receiver; cin receiver; balance[receiver] gift; } } for (const auto name : names) { cout name balance[name] endl; } } return 0; }3.2 关键实现细节输入处理使用while循环处理多组测试用例使用first_case标志控制空行输出确保最后一组后也有空行金额计算整数除法自动向下取整符合题目要求先计算总送出金额再逐个增加接收者金额输出顺序使用vector保存原始顺序确保输出与输入顺序一致4. 常见错误与调试技巧4.1 典型错误模式输出格式错误忘记在每组输出后加空行最后一组也必须有空行输出顺序与输入不一致边界条件处理不足NG0时出现除零错误赠送金额为0时错误分配名字大小写不匹配金额计算错误未使用整数除法赠送者金额扣除不正确接收者金额增加不正确4.2 调试建议使用小型测试用例2 Alice Bob Alice 100 1 Bob Bob 0 0预期输出Alice -100 Bob 100极端情况测试最大NP10金额为0NG0名字长度刚好12字符使用printf调试cerr Processing giver giving amount to NG people endl;5. 算法优化与变种思考5.1 性能优化虽然本题数据量很小不需要优化但可以考虑使用数组代替vector和map通过索引访问提前计算好所有输入再统一处理5.2 题目变种如果赠送金额不是平均分配而是按特定比例如果允许赠送金额为负数借贷如果参与人数NP很大如1e5级别如果名字很长如100字符5.3 实际应用扩展这类问题在实际中可用于财务记账系统团体活动费用分摊社交网络中的虚拟货币流通模拟6. 在线评测注意事项UVa Online Judge的特殊要求必须使用文件结束符(EOF)判断输入结束输出必须完全匹配包括空格和换行使用\n而不是endl可能更快减少flush提交前的检查清单所有边界条件是否处理输出格式是否正确变量是否初始化输入输出是否同步cin/cout与scanf/printf混用问题评测结果解读WA (Wrong Answer)检查输出格式和逻辑RE (Runtime Error)检查数组越界和除零TLE (Time Limit)虽然本题不太可能检查是否有死循环7. 个人实现心得在实际解决这个问题时我最初犯了两个典型错误一是忽略了NG0的情况导致除零错误二是没有保持原始输出顺序直接遍历map导致顺序错乱。调试过程中我总结了几个有用的技巧先写输入输出框架确保格式正确处理每个赠送者时先打印中间状态验证使用小型测试用例手动计算预期结果特别注意题目中的每组输出后跟一个空行要求这道题虽然简单但很好地训练了对问题描述的精确理解和边界条件的全面考虑能力。在编程竞赛中这类模拟题往往是区分新手和有经验选手的关键——不是算法复杂度而是对细节的把握。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑