题目大意:
n和村庄各自有自己的金币,相邻村庄可以互相给金币。为了实现共产主义,现在要实现每个村庄的金币数量都相同。求出最小的金币转移量。
题目思路:
1.设 a[ i ] 表示第 i 个村庄有的金币。
2.设 b[ i ] 表示第 i 个村庄给 i-1个村庄的金币。
3.设 M 表示最后每个村庄有的金币
则可以列出方程式
4.每个b都可以用 b[ 1 ]来表示,则有
5.设 c[ i ] 表示b[ i ] 是右值中除了b[ 1 ] 的部分则有
6.我们要求的是(让这个值尽可能的小):
即c数组中每个点到到某点的距离之和最小(即c数组中的中位数)。可以联想一下曼哈顿距离。
我们知道c[ 0 ] 是0,可以递推求出c数组中的所有值,求出中位数后求出距离之和即答案。
#include<cstdio>
#include<cmath>
#include<algorithm>
#define N 1000001
#define LL long long
using namespace std;
LL a[N];
LL b[N];
int n;
int main(){
while(scanf("%d",&n)!=EOF){
LL sum = 0;
//输入数据
for(int i=0 ;i<n ;i++){
scanf("%lld",&a[i]);
sum += a[i];
}
int M = sum/n;
//递推求出b数组
b[0] = 0;
for(int i=1 ;i<n ;i++){
b[i] = b[i-1]+a[i]-M;
}
sort(b,b+n);
//求与中位数的距离之和
LL ans = 0;
for(int i=0 ;i<n ;i++){
ans += abs(b[i]-b[n/2]);
}
printf("%lld\n",ans);
}
return 0;
}