11300 - Spreading the Wealth

(解方程建模+中位数求最短累积位移)


分金币(Spreading the Wealth, UVa 11300)

  圆桌旁坐着n个人,每人有一定数量的金币,金币总数能被n整除。每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数目相等。你的任务是求出被转手的金币数量的最小值。比如,n=4,且4个人的金币数量分别为1,2,5,4时,只需转移4枚金币(第3个人给第2个人两枚金币,第2个人和第4个人分别给第1个人1枚金币)即可实现每人手中的金币数目相等。

【输入格式】

输入包含多组数据。每组数据第一行为整数nn≤1 000 000),以下n行每行为一个整数,按逆时针顺序给出每个人拥有的金币数。输入结束标志为文件结束符(EOF)。

【输出格式】

对于每组数据,输出被转手金币数量的最小值。输入保证这个值在64位无符号整数范围内。

【样例输入】

 

3

100

100

100

4

1      

2        

5       

4       

 

【样例输出】

0

4



【思路】:




C0 = 0
C1 = A1 - M = C0 + A1 - M
C2 = A1 - M + A2 - M = C1 + A2 - M
............
Cn = An-1 - M + An - M = Cn-1 + An - M

规律:Cn  = Cn-1 + An - M
#include<cstdio>
#include<algorithm>
using namespace std;
int Money[1000001],C[1000001];
int cmp(const void* a,const void *b)
{
    return *(int*)a-*(int*)b;
}
int abs(int a,int b){
    if(a<b) return b-a;
    else return a-b;
}
int main()
{
    long long i,N,sum,min,M;
    while(scanf("%lld",&N)!=EOF){
        sum=0;
        min=0;
        for(i=0;i<N;i++){
            scanf("%d",Money+i);
            sum+=Money[i];
        }
        M=sum/N;
        for(int i=1;i<N;i++){
            C[i]=C[i-1]+Money[i]-M;
        }
        qsort(C,N,sizeof(int),cmp);
        long long int x1=C[N/2];
        for(i=0;i<N;i++){
            min+=abs(x1,C[i]);
        }
        printf("%lld\n",min);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值