UVA11300 Spreading the Wealth

弱智商的碰到这种题就是跪啊!!!!

题意:圆桌坐着N个人,每个人有一定的金币,金币总数能被N整除。每个人能给左右相邻的人一些金币,最终使得每个人的金币数目相等,求被转手金币数量的最小值。

设 xi表示i号给i-1号xi金币,若xi为负,这表示i-1号给i号(-xi)个金币

Ai表示i号一开始持有的金币

则:对与第1个人:A1-X1+X2=M  ===>X2=X1-(A1-M);令C1=A1-M

  对于第2个人:A2-X2+X3=M ====>x3=x2-(A2-M) ====>x3=x1-(A1+A2-2M);===>x3=x1-C2;

  ……

  对于第n个人:An-Xn+x1=M 这个是个恒等式,无用;

  所以我们的答案应该是 |X1|+|X2|+|X3|+……+|Xn|的最小值;

  ====>|X1|+|X1-C1|+|X1-C2|+……+|Xn-1-Cn|的最小值

  故当X1取C数组的中间值时,结果最小。。。

View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 1000000+50
#define LL long long
LL C[MAXN];
LL A[MAXN];
int n;

int main()
{
    while(~scanf("%d",&n)){
        LL sum=0;
        for(int i=0;i<n;i++){
            scanf("%lld",&A[i]);
            sum+=A[i];
        }
        LL M=sum/n;
        sum=0;
        for(int i=0;i<n-1;i++){
            sum+=A[i];
            C[i]=sum-(i+1)*M;
        }
        sort(C,C+n-1);
        LL x=C[(n-1)/2];
        LL ans=abs(x);
        for(int i=0;i<n-1;i++){
            ans+=abs(x-C[i]);
        }
        cout<<ans<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/arbitrary/p/2841522.html