/*
有n个小朋友坐成一圈,每人有Ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1,求使所有人获得均等糖果的最小代价。
假设当前n个小朋友手中的糖果数量是
a[ 1 ] , a[ 2 ] , ...... , a[ n ]
那么总共的糖果量是
sum_ = a[ 1 ] + a[ 2 ] + ...... + a[ n ]
平均值,即传苹果结束的时候每个人手中剩余苹果量是:
average = sum / n
第一步,第1个小朋友给了第n个小朋友k(可能为正、负、0)个苹果(暂且不要管为什么这样,只需要他这么做了)
付出代价是|k|
这时候第1个小朋友手中的苹果数量是:
a[ 1 ] - k
第二步,为了保证第1个小朋友手中苹果为average,需要从第2个小朋友中拿,拿多少呢?
average-(a[1]-k)= average-a[1]+k
付出代价是
| average-a[1]+k |
第2个小朋友剩下多少呢
a[2]-( average-(a[1]-k) )=a[2]+a[1]-average-k
第三步,为了保证第2个小朋友手中苹果为average,需要从第3个小朋友中拿,拿多少呢?
average-( a[2]+a[1]-average-k ) = 2*average-a[1]-a[2]+k
付出代价是
|2*average-a[1]-a[2]+k|
第3个小朋友剩下多少呢
a[3]-( 2*average-a[1]-a[2]+k ) = a[3]+a[2]+a[1]-2*average-k
第N步,为了保证第N-1个小朋友手中苹果为average,需要从第N个小朋友中拿,这时候付出的代价是
|a[n-1]+a[n-2]+......+a[2]+a[1]-n*average-k|
显然,这时候第n个位置剩余苹果数也是average,因为n-1个位置都是average了,只有一个average剩下,即在第n个位置
经过上面分析,总共需要付出的代价是
|k|
+|average-a[1]+k|
+|2*average-a[1]-a[2]+k|
+
.
.
.
+
|n*average+k-a[n-1]-a[n-2]-......-a[2]-a[1]|
或者表示为
S=
|k|
+|(a[1]-average)-k|
+|(a[1]-average)+(a[2]-average)-k|
+
.
.
.
+
|(a[1]-average)+(a[2]-average)+......+(a[n-1]-average)-k|
假设有一个数组b,其内容分别是
b[1] = 0
b[2] = (a[1]-average)
b[3] = (a[1]-average)+(a[2]-average)
.
.
.
b[n] = (a[1]-average)+(a[2]-average)+......+(a[n-1]-average)
那么b数组就可以表示成数轴上面的n个点
S就可以表示“在数轴上选一个点k,数组b中每个元素对应的点到点k的距离的和”
这个点k应该是多少呢?应该是数组b的中位数,求出中位数,即可得出最小的S。
这个k的有效取值范围是多少呢?我自己觉得是[-a[n],a[1]],即最多1把自己全部苹果给n;最小,n把全部苹果给1
这个利用了中位数一个性质
*/
//假设n可以整除所有苹果的总和
#include<algorithm>
#include<iostream>
using namespace std;
int main() {
int a[ 100 ];
int b[ 100 ];
int n;
int i;
int sum = 0;
int average = 0;
int mid = 0;
int result = 0;
scanf( "%d" , & n );
for( i = 1 ; i <= n ; i ++ ) {
scanf( "%d" , & a[ i ] );
sum += a[ i ];
}
//求平均值
average = sum / n;
cout << average << endl;
//求数组b
b[ 1 ] = 0;
for( i = 2 ; i <= n ; i ++ ) {
b[ i ] = b[ i - 1 ] + a[ i - 1 ] - average;
}
//排序,为了求中位数
sort( b + 1, b + n + 1 );
//求中位数
if( n % 2 == 0 ) {
mid = ( b[ ( n + 1 ) / 2 ] + b[ ( n + 1 ) / 2 - 1 ] ) / 2;
}
else {
mid = b[ ( n + 1 ) / 2 ];
}
//求代价
for( i = 1 ; i <= n ; i ++ ) {
result = result + abs( mid - b[ i ] );
}
cout << result << endl;
return 1;
}
平分糖果---2013阿里笔试题
最新推荐文章于 2024-02-18 21:42:40 发布