转载自:http://www.cnblogs.com/yejinru/archive/2012/12/29/2838467.html,尊重原创!
/*
* 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1045
* 有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传
* 递一个糖果代价为1,求使所有人获得均等糖果的最小代价。
*
* 分析:
* 假设a1分给an的糖果数为k,则可以得到以下的信息:
* a1 a2 a3 an-1 an
* 当前数目:a1-k a2 a3 an-1 an+k
* 所需代价:|a1-k-ave| |a1+a2-k-2*ave| |a1+a2+a3-k-3*ave| |a1+..+a(n-1)-k-(n-1)*ave| |k|
* 以sum[i]表示从a1加到ai减掉i*ave的和值,这以上可以化简为
* 总代价 = |s1-k|+|s2-k|+...+|s(n-1)-k|+|k|
* 不难看出:当k为s1...s(n-1)中的中位数的时候,所需的代价最小
*
* */
1 <span style="font-size: 15px;">#include <cstdio> 2 3 #include <cstring> 4 5 #include <iostream> 6 7 #include <algorithm> 8 9 10 11 using namespace std; 12 13 14 15 const int X = 1000005; 16 17 18 19 typedef long long ll; 20 21 22 23 ll sum[X],a[X]; 24 25 ll n; 26 27 28 29 ll Abs(ll x){ 30 31 return max(x,-x); 32 33 } 34 35 36 37 int main(){ 38 39 //freopen("sum.in","r",stdin); 40 41 while(cin>>n){ 42 43 ll x; 44 45 ll tot = 0; 46 47 for(int i=1;i<=n;i++){ 48 49 scanf("%lld",&a[i]); 50 51 tot += a[i]; 52 53 } 54 55 56 57 ll ave = tot/n; 58 59 for(int i=1;i<n;i++) 60 61 sum[i] = a[i]+sum[i-1]-ave; 62 63 sort(sum+1,sum+n); 64 65 66 67 ll mid = sum[n/2]; 68 69 ll ans = Abs(mid); 70 71 72 73 for(int i=1;i<n;i++) 74 75 ans += Abs(sum[i]-mid); 76 77 cout<<ans<<endl; 78 79 } 80 81 return 0; 82 83 } 84 85 </span>