2239: 午餐的最优排队
Description
午餐铃一响,食堂唯一的打饭窗口前排起了长队。教务处想用算法决定排队顺序,让全体同学等待时间的总和最小,并且对“谁排最后”给出一个明确的说法。
题目描述
N 位同学在唯一一个窗口排队,第 i 位同学打饭需要 t[i] 秒。排在第 p 位的同学的等待时间 = 排在他前面的所有同学打饭时间之和(不含自己),第一个打饭的同学等待时间为 0。
请你确定一个排队顺序,使所有同学等待时间的总和最小,并输出两个数:
1. 最小总等待时间;
2. 在达到最小总等待时间的排队顺序中,排在最后一位的同学的编号的最小可能值。
Input
第一行一个整数 N。第二行 N 个整数 t[1] … t[N]。
Output
一行两个整数:最小总等待时间、最后一位编号的最小可能值。
Sample Input Copy
4
2 5 5 1
Sample Output Copy
12 2
样例解释:
最优顺序为 4号(1秒)、1号(2秒)、2号(5秒)、3号(5秒),等待 0、1、3、8,总和 12。最后一位在 2 号与 3 号中产生,编号最小为 2。注意:打饭时间相同的同学互换位置,总和不变。
HINT
1 ≤ N ≤ 5000,1 ≤ t[i] ≤ 1000。提示:注意总等待时间的数值规模。
AI 辅助编程建议
①确认需求。 让 AI 复述:等待时间的定义(只等前面的人、不含自己、第一位为 0);“总等待时间最小”的含义;第二个输出的前提是“在最优顺序中”,并请它说明打饭时间相同的同学互换位置时总和为什么不变。
②生成程序。 要求 AI 先说理再写代码:交换相邻的两个人,算一算总等待时间如何变化,从而论证“打饭时间短的排前面”是最优的。若指定 C++,请它说明总等待时间用什么类型存放,并估算 N=5000、t 全为 1000 时总和的量级。
③审查逻辑。 重点检查三处:贡献法公式方向——排第 i 位(从 0 数起)的人,其打饭时间会被后面 n−1−i 个人各“等”一次,因此总和 = Σ t[i]×(n−1−i),检查系数有没有写反;最后一位必须在“打饭时间最长的人”里挑编号最小的,不要顺手写成“编号最大”;N=1 时总等待为 0。
④补充测试。 除题面样例外,还应检查:N=1;所有人打饭时间相同(验证末位编号取最小);数据已升序与逆序两种输入;打饭时间大量重复的数据;N=5000 且 t 全为 1000 的最大规模(专测数值溢出,正确答案为 12497500000)。
⑤迭代修正。 如果实际输出与预期不一致,把输入、预期输出和实际输出一并提供给 AI,并说明怀疑方向(例如“是不是没排序”“是不是溢出了”);修改后重新运行全部测试。