zoukankan      html  css  js  c++  java
  • 题目分享L

    题意:n个人围成一个环,每个人初始有一些金币,每个人可以把金币递给相邻的人,问最少传递多少金币使每个人金币数相同?

    分析:首先在保证最优的情况下不可能会出现相邻的两个人互相送金币,因为这样他们公共的部分等于没送,那么我们就可以用bi来表示i号人往左边送的金币,可以为负,为负就表示左边送回来,那么,如果设p为金币相等时每人的金币数(总金币的平均数),ai为i号人原始的金币数,那么很容易得到:

    a1-b1+b2=p

    a2-b2+b3=p

    ……

    an-bn+b1=p

    而我们要求的是bi的绝对值之和,所以再转化一下

    b2=p-a1+b1

    b3=p-a2+b2

    ……

    bn=p-an+bn-1

    然后将所有右试中b2-bn-1代换为b1即

    b2=p-a1+b1

    b3=p-a2+(p-a1+b1)=p-a1+p-a2+b1

    ……

    bn=p-a1+p-a2+……+p-an-1+b1

    而p,a1-an都是常数,输入都给了,所以我们把它写成c使我们看起来方便一些

    |b1|=|b1|       //这里也可以写成  |b1|=|b1-c1|    ,c1=0

    |b2|=|b1-c2|  ,c2=a1-p

    |b3|=|b1-c3|  ,c3=a1-p+a2-p

    ……

    |bn|=|b1-cn|  ,cn=a1-p+a2-p+……+an-1-p

    为什么要写成b1-ci的形式呢?

    因为|a-b|相当于在数轴上a与b的距离

    所以最终的结果是 |b1| + |b2| + |b3| + …… + |bn| =|b1-c1| + |b2-c2| + …… + |bn-cn| 

    而只有b1是未知数,所以其实最终结果就是在数轴上离c1,c2,……,cn距离之和的最小值

    而这应该初中的时候都学过

    将这n个点在数轴上表示出来

    这时的c1-cn我将它看做原c数组从小到大排完序后的数组

    那么显然为了保证|b1-c1|+|b1-cn|的值最小,b1应该在c1-cn之间

    为保证|b1-c2|+|b1-cn-1|的值最小,b1应该在c2-cn-1之间

    ……

    最后如果n是偶数的话,b1取cn/2到cn/2+1之间的值都可以

    如果n是奇数的话,b1只能取c(n+1)/2 

    为了方便我们之间让b1=c(n+1)/2就可以了

    这里求c(n+1)/2可以用nth_element() O(n) 有兴趣可以去cplusplus学一下,当然sort也是可以的

    最后将b1的值带去原式子中计算就行

    代码:

  • 相关阅读:
    gdb调试libtool封装的可执行文件
    转载 Linux top命令详解
    VirtualBox使用物理硬盘建立磁盘
    【sqlServer】常用语句整理
    【c#基础】特殊集合
    【c# 基础】各种集合的不同情况下的性能
    【c#集合】Lookup 类 有序字典 SortedDictionary<TKey,TValue> 集
    【c#基础】集合--栈Stack 链表 LinkList 有序列表SortedList 字典Dictionary
    【c#基础】集合
    【c#基础】委托、Lambda表达式和事件
  • 原文地址:https://www.cnblogs.com/lin4xu/p/12661849.html
Copyright © 2011-2022 走看看