题目链接:点击查看
题目大意:现在有 n 个队伍参加比赛,任意两个队伍之间都要进行一次比赛,也就是共需要进行 n * ( n - 1 ) / 2 次比赛,对于每个队伍来说,必须要在第一场比赛的时候到达赛场,在最后一场比赛结束后离开赛场,在赛场上呆的时间即为贡献,现在求出一种比赛的安排顺序,使得每个队伍的贡献之和最小
题目分析:可以自己手玩一下找找规律,这里以 n = 6 为例,画个图:
上图中表示了 n * ( n - 1 ) / 2 场比赛按照升序排列后,也就是按照红色箭头的方向依次比赛,相信肯定有不少同学在看完样例后以为这样是最优的,于是莽了一发,结果得到的是答案错误吧
我来一步一步优化一下整体序列,使得每次都变的最优吧,首先求一下当前情况下,每个队伍需要在赛场上滞留的天数
接下来我们不难发现,如果尝试将 ( 2 , 3 ) 这个点移到 ( 1 , 3 ) 之后,可以使得队伍 1 的贡献加一,队伍 2 和队伍 3 的贡献不变,队伍 4 , 5 , 6 的贡献减一,显然这样是更优的,于是我们移动一下
在此基础上,我们发现前移 ( 2 , 4 ) 也是可以让贡献减少,于是再次更新顺序
到此为止,可以得到当 n = 6 的答案序列了,是不是没有看出任何规律?好,那我们继续将 ( 2 , 5 ) , ( 2 , 6 ) 和 ( 3 , 4 ) 分别移动到相应的位置,看看结果会发生什么样的变化
到此为止,差不多就可以稍微总结一下结论或者规律了, 首先默认初始时比赛的顺序为最初的升序排列,对于一比赛不妨设为 ( i , j ) 满足 i < j ,如果将 ( i , j ) 前移(先不要管将其移动到什么位置),则对整体的贡献就是,i 前面的队伍,贡献会 +1 ,j 后面的队伍,贡献会 -1,用公式表达的话,( i , j ) 前移的贡献就是 sum += ( i - 1 ) - ( n - j ) ,也就是说,对于一场比赛我们可以分为三种情况:
推广一下发现这个结论对所有的 ( i , j ) 都适用,剩下的就是在三个部分中,各自排序的问题了,在上面手动模拟后,看的出中间部分和后面部分按照升序排列就好了,而前半部分需要按照 j 的升序排列,当 j 相同时再按照 i 的升序排列
证明的话我也不会,毕竟是比赛时找规律乱搞出来的,不过看完之后应该感觉还是比较有道理是吧?
实现就比较简单了
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include