糖果传递问题
题目描述
有 n 个小朋友坐成一圈,每人有 a[i] 个糖果。
每人只能给左右两人传递糖果。
每人每次传递一个糖果代价为 1。
求使所有人获得均等糖果的最小代价。
输入格式
第一行输入一个正整数 n,表示小朋友的个数。
接下来 n 行,每行一个整数 a[i],表示第 i 个小朋友初始得到的糖果的颗数。
输出格式
输出一个整数,表示最小代价。
输入输出样例 #1
输入 #1
4
1
2
5
4
输出 #1
4
输入输出样例 #2
输入 #2
5
1
2
3
4
5
输出 #2
5
限制条件
- 1≤n≤1000000
- 0≤a[i]≤2×109
- 数据保证一定有解
样例解释 #1
初始糖果数:[1,2,5,4]
平均糖果数:41+2+5+4=3
需要传递糖果使每人都有 3 个糖果。
一种最优方案:
- 第 3 个小朋友给第 2 个小朋友 1 个糖果(第 2 个小朋友现在有 3 个,第 3 个有 4 个)
- 第 3 个小朋友给第 4 个小朋友 1 个糖果(第 4 个小朋友现在有 5 个,第 3 个有 3 个)
- 第 4 个小朋友给第 1 个小朋友 2 个糖果(第 1 个小朋友现在有 3 个,第 4 个有 3 个)
总传递糖果数:1+1+2=4,代价为 4。
数学模型
设最终每人糖果数为 avg=n∑i=1na[i]。
设 xi 表示第 i 个小朋友给第 i−1 个小朋友的糖果数(正数表示给,负数表示收)。
则对于第 i 个小朋友:
a[i]−xi+xi+1=avg (注意 xn+1=x1,因为是环形)
整理得:
xi+1=xi+(avg−a[i])
令 ci=∑j=1i(a[j]−avg),则有:
xi+1=x1−ci
总代价为 ∑i=1n∣xi∣。
问题转化为:求一个 x1,使得 ∑i=1n∣x1−ci−1∣ 最小(其中 c0=0)。
这是一个经典的货仓选址问题,最优解为取 ci−1 的中位数作为 x1。
算法步骤
- 计算平均值 avg
- 计算前缀和 ci=∑j=1i(a[j]−avg)
- 将 c 数组排序
- 取中位数 mid=c⌊2n⌋
- 计算 ∑i=0n−1∣mid−ci∣ 即为答案