UVA 11300 Spreading the Wealth

题目链接:https://vjudge.net/problem/UVA-11300
题目大意:圆桌边坐着n个人,每个人有一定数量的金币,每个人通过给相邻的人一定量的金币,做到最终每个人所拥有的金币相等,求出转手的金币的总和的最小值
题目思路:设每个人初始拥有的金币为Ai,xi表示第i个人给第(i+1)个人(第n个人给第1个人),如果xi是负数则表示是反向给金币,记M=(A1+A2+…+An)/n,那么有如下n个等式,Ai - xi + xi+1 = M(i为1~n),将x1以外的其他xi表示为x1的表达式,转手金币的总和可以表达为abs(x1)+abs(x1-c1)+abs(x1-c2)+...+abs(x1-cn-1),ci表示化简过程中的常数。那么问题就转化为了在数轴上有n-1个数,求x1到这n-1个数的距离之和最小。总所周知,这个x1是这n-1个数的中位数,那么就可以解决了。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1000005;
ll arr[maxn];
ll c[maxn];
int main()
{
    int n;
    while(~scanf("%d", &n))
    {
        ll sum = 0;
        ll avg = 0;
        for(int i = 1; i <= n; i ++)
        {
            scanf("%lld",&arr[i]);
            sum += arr[i];
        }
        avg = sum / n;
        for(int i = 1; i <= n - 1; i ++) c[i] = c[i - 1] + arr[i] - avg;
        sort(c + 1, c + n);
        ll x1 = c[(n + 1) / 2];
        sum = 0;
        for(int i = 1; i <= n;i ++) sum += abs(x1 - c[i]);
        printf("%lld\n",sum);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/goxy/p/9643563.html
今日推荐