zoukankan      html  css  js  c++  java
  • UVa 11300 Spreading the Wealth(有钱同使)

    UVa 11300 - Spreading the Wealth(有钱同使)

    Time limit: 6.000 seconds


    Description - 题目描述

    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.

    某村子准备重新分配财富进一步迈向共产主义。他们已召集好全部人等围坐在圆桌前。首先,每个人都把其全部财富转换为若干等价的硬币。然后将硬币总数除以村子人数。最后,每个人可以分别给予左右两人若干硬币,使得所有人的硬币数量相同。给你每个人的初始硬币数量,计算最少需要转移多少枚次(比对“人次”)硬币才能按上述方法完成最终分配。
    CN

      

    Input - 输入

    There is a number of inputs. Each input begins with n (n < 1000001), the number of people in the village. n lines 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.

    多组测试用例。每组以n(n < 1000001)打头,表示这个村子的总人数。随后n行以逆时针顺序给出桌上每个人的硬币数量。硬币的总数少于无符号64位整数。(然而实际情况似乎用有符号64位就能解决)
    CN

     

    Output - 输出

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

    对于每组测试用例,输出一行最少需要转移的硬币枚次。
    CN

     

    Sample Input - 输入样例

    3
    100
    100
    100
    4
    1
    2
    5
    4
    

     

    Sample Output - 输出样例

    0
    4
    

     

    题解

    绝对值不等式的题目,选好推倒的关系很快就能推出来。题目似乎在数据放水了,没有出到unsigned 64。

    设:

      第i个人给下一个人的硬币为Ci(其值可正可负)

      第i个人初始硬币为Pi,第1~i个人的硬币之和为Spi

      平均数为A

     

    则:

    P1 + Cn - C1 = A
    
    P2 + C1 - C2 = A
    
    P3 + C2 - C3 = A
    
    ................
    
    Pn + Cn-1 - Cn = A
    

     

    最终需要求的流动硬币的数量S = |C1| + |C2| + |C3| + ... + |Cn|

     

    因此后面开始把C1 ~ Cn 化简出来:

          C1 = P1 - A + Cn = Sp1 - A + Cn
    
          C2 = P2 - A + C1 = Sp1 + P2 - 2A + Cn = Sp2 - 2A + Cn
    
          C3 = P3 - A + C2 = Sp2 + P3 - 3A + Cn = Sp3 - 3A + Cn
    
          C4 = P4 - A + C3 = Sp3 + P4 - 4A + Cn = Sp4 - 4A + Cn
    
          ......................
    
          Cn = Spn - nA + Cn
    

     

    此时已经找出递推式了,后面为了说明简单,令Cpn = Spn - nA

          S = |C1| + |C2| + |C3| + ... + |Cn|
    
          S = |Cp1+Cn| + |Cp2+Cn| + |Cp3+Cn| + ... |Cpn+Cn|
    

     

    最后一个|Cpn+Cn|已经是0了,可以忽略掉:)

    得到了S的表达式,我们要做的就是求最小值,由于S >= 0,很容易想到绝对值不等式。

    |Cp1+Cn| + |Cp2+Cn| + |Cp3+Cn| + ... |Cpn+Cn| >= 0

    如果取最小值,则 Cn = -(Cp1 ~ Cpn的中位数)。(n为偶数时靠左靠右无所谓,画个图就知道了:)

    奇数 

     

    偶数

    代码 C++

     1 #include <cstdio>
     2 #include <algorithm>
     3 long long Sp[1000001], Cp[1000001];
     4 int main(){
     5     int n, i;
     6     long long opt, Avg, Cn;
     7     while (~scanf("%d", &n)){
     8         for (i = 1; i <= n; ++i){
     9             scanf("%lld", &Sp[i]); Sp[i] += Sp[i - 1];
    10         }
    11         Avg = Sp[--i] / n;
    12         for (i = 1; i <= n; ++i) Cp[i] = Sp[i] - Avg*i;
    13         std::sort(Cp + 1, Cp + 1 + n); opt = 0;
    14         Cn = -Cp[1 + n >> 1];
    15         for (i = 1; i <= n; ++i){
    16             if ((Cp[i] += Cn) < 0) Cp[i] = -Cp[i];
    17             opt += Cp[i];
    18         }
    19         printf("%lld
    ", opt);
    20     }
    21     return 0;
    22 }

     

     

  • 相关阅读:
    【算法学习笔记】76.DFS 回溯检测 SJTU OJ 1229 mine
    【算法学习笔记】75. 动态规划 棋盘型 期望计算 1390 畅畅的牙签盒(改)
    【算法学习笔记】74. 枚举 状态压缩 填充方案 SJTU OJ 1391 畅畅的牙签袋(改)
    【算法学习笔记】73.数学规律题 SJTU OJ 1058 小M的机器人
    【算法学习笔记】72.LCS 最大公公子序列 动态规划 SJTU OJ 1065 小M的生物实验1
    【算法学习笔记】71.动态规划 双重条件 SJTU OJ 1124 我把助教团的平均智商拉低了
    【算法学习笔记】70.回文序列 动态规划 SJTU OJ 1066 小M家的牛们
    【算法学习笔记】69. 枚举法 字典序处理 SJTU OJ 1047 The Clocks
    【算法学习笔记】68.枚举 SJTU OJ 1272 写数游戏
    【算法学习笔记】67.状态压缩 DP SJTU OJ 1383 畅畅的牙签袋
  • 原文地址:https://www.cnblogs.com/Simon-X/p/5938084.html
Copyright © 2011-2022 走看看