题意:给你n个人以及每个人现有的钱数让他们围成一个环,一个人只能接受或者赠予和他相邻的人金币,问你最少要交换几个金币可以使每个人拥有的钱数一样。
思路:首先明确一点就是1给2之后2在给1这样的情况肯定是不允许的,这样他们就“浪费”了一些金币对吧,那么我们现在假设现在有4个人,1号赠予4号的金币数是X4,1号接受2号的金币数是X1,我们可以算出来最终每个人最后金币相等时的金币数M
那么可以得到等式 X1-X4+A[1] = M ,以此类推还有
X4 - X3 + A[4] = M
X3 - X2 + A[3] = M;
X2 - X1 + A[2] = M;
最后我们等式替换成只含X1的等式最后可有
X2 = X1+A[1] - M;
X3 = X1+A[1] - M + A[2] - M;
X4 = X1+A[1] - M + A[2] - M + A[3]-M
最后我们把他变成 之后我们要求的时 abs(X1)+abs(X2)+abs(X3)+abs(X4)最小是吧
那么我们我们把他映射到数轴上有
那也就是说我们现在要找到这样一个点X1,是C1,C2,C3这几个点到X1的距离最小,emm我们利用一下比较敏锐的数学思想应该可以推理出在在中位数的时候X1的距离最小,emm具体证明就是,首先X1一定要在C1..C3的点上,因为如果在数轴上我们会平白多出一些距离,那么在哪里最划算呢,就是在中位数的时候。。(xjb整 >。<)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000001+10;
long long sum = 0 ;
long long A[maxn],X[maxn];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
sum = 0;
for(int i = 0 ; i < n ;i++)
{
scanf("%lld",&A[i]);
sum+=A[i];
}
int M = sum/n;
X[0] = 0;
for(int i = 1 ; i < n ; i++)
{
X[i] = X[i-1] + A[i-1] - M;
}
sort(X,X+n);
long long ans = 0;
int te = X[n/2];
for(int i = 0 ; i < n ; i++)
{
ans+= abs(te - X[i]);
}
printf("%lld\n",ans);
}
}