UVA-11300 - Spreading the Wealth

本文介绍了一种解决圆桌上N个人通过相互传递金币达到每人持有相同数量金币的问题算法。该算法利用数学模型,通过设定变量并建立等式,最终确定了最小金币转移数量的计算方法。

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

题意:圆桌坐着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/archive/2013/01/01/2841522.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值