zoukankan      html  css  js  c++  java
  • UVa 11300 Spreading The Wealth

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2275

     F. Spreading the Wealth 

    Problem

    A Communist regime is trying to redistribute wealth in a village. They have have decided to sit everyone around a circular table. First, everyone has converted all of their properties to coins of equal value, such that the total number of coins is divisible by the number of people in the village. Finally, each person gives a number of coins to the person on his right and a number coins to the person on his left, such that in the end, everyone has the same number of coins. Given the number of coins of each person, compute the minimum number of coins that must be transferred using this method so that everyone has the same number of coins.

    The Input

    There is a number of inputs. Each input begins with n(n<1000001), the number of people in the village. nlines follow, giving the number of coins of each person in the village, in counterclockwise order around the table. The total number of coins will fit inside an unsigned 64 bit integer.

    The Output

    For each input, output the minimum number of coins that must be transferred on a single line.

    Sample Input

    3
    100
    100
    100
    4
    1
    2
    5
    4
    

    Sample Output

    0
    4
    

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

    分析:用M表示每人最终拥有的金币数。假设有4个人,编号1,2,3,4,。假设1号给2号3枚金币,2号又给1号5枚金币,实际等价于2号给1号2枚金币,而1号什么也没给2号。这样可以设x2表示2号给了1号多少枚金币。如果x2<0,说明1号给了2号-x2枚金币。x1,x3,x4含义类似。注意,由于是环形,x1指1号给4号多少金币。

    先假设编号为i的人最初由A[i]枚金币。对1号来说,他给了4号x1枚金币,又从2号获得了x2枚金币,最后剩下A[1]-x1+x2。根据假设,A[1]-x1+x2=M.

    同理,对第二个人,由A[2]-x2+x3=M。

    因此,对于第一个人:A[1]-x1+x2=M  → x2=x1-C[1](规定C[1] = A[1]-M)

             对于第二个人: A[2]-x2+x3=M  → x3=x2-(A[2]-M)=x1-C[1]-(A[2]-M) = x1-C[2]  (C[2] = C[1]+A[2]-M,以下类似)

             ······

    我们希望所有xi的绝对值之和尽量小,即|x1|+|x1-C[1]|+|x1-C[2]|+······+|x1-C[n-1]|要最小,注意到|x1-C[i]|的几何意义是数轴上点x1到C[i]的距离。所以问题就变成了:给定数轴上的n个点,找出一个到它们距离之和尽量最小的点。

    这个最优的距离x1就是这些数的“中位数”(即排序后位于中间的数),因此只要做个排序即可。证明请在网上搜索。

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    #define maxn  1000010
    int n;
    long long a[maxn], sum, c[maxn];
    int main()
    {
        while(~scanf("%d", &n))
        {
            sum = 0;
            for(int i = 1; i <= n; i++)
            {
                scanf("%lld", &a[i]);
                sum += a[i];
            }
            long long m = sum/n;
            c[0] = 0;
            for(int i = 1; i < n; i++)
                c[i] = c[i-1]+a[i]-m;
            sort(c, c+n);
            long long x1 = c[n/2];
            long long ans = 0;
            for(int i = 0; i < n; i++)
                ans += abs(x1-c[i]);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    [HNOI2012]矿场搭建
    舞蹈链
    POJ Apocalypse Someday
    扩展卢卡斯定理
    矩阵求逆
    RandomAccsiFile
    1.单例设计模式
    MySQL 7.多表操作
    IO流之Properties(配置文件)
    MySQL 6.子查询
  • 原文地址:https://www.cnblogs.com/dzkang2011/p/zhongweishu.html
Copyright © 2011-2022 走看看