UVa 11300
来源:互联网 发布:七月煤炭进出口数据 编辑:程序博客网 时间:2024/06/04 18:40
题目链接
题目描述:
圆桌旁坐着n个人,每个人有一定数目的金币,金币总数能被n整除。每个人可以给相邻的人一些金币,最终使得每个人的金币数目相等,求被转手的金币数量的最小值。
输入第一行为整数n
接下来n行每行代表第i个人持有的金币数Ai
输出:被转手金币的最小值。
分析:首先每个人的最终状态我们是能确定的,因为最终金币相等,我们在读取时累计,读取结束后 m = sum / n 就是这个最终值。
令xi : 第i个人给了第i-1个人多少个金币(因为是一个圆桌,所以第1个人左边是第n个人,即当i = 1时 i-1 = n)
xi<0时相当于第i-1个人给第i个人金币
那么对每一个人来说: m = Ai - xi + x(i+1) 为什么不考虑i给i+1个人多少金币 因为这是可以相互转化的,比如1号给2号金币 然后2号又给1号金币 这样可以都转化为2号给1号金币
那么 x1 = Ai + x2 - m
x(i+1) = m - Ai + xi-1
即 x2 = m - A2 + x1 = x1 - C1
x3 = m - A2 + x2 = m-A3 +(m - A2 + x1) = 2*m - A3 - A2 +x1 = x1-C2
····
递推时发现每个xi都可以用一个常数+x1来代替
这样我们可以得到n个等式,但由于xn是可以由x1和xn-1得到的,所以我们实际上只得到了n-1个等式。
这样,我们换个角度,我们希望所有xi的绝对值之和尽量小,即|x1| + |x1 -C1| + |x-C2|+```|x1-Cn-1| 尽量小
把每一个C放到数轴上,我们要求的就是x1的位置,使得x1到所有C的距离之和最小
答案是: x1是所有C这个序列的中位数
实际上这是一个邮局选址问题:
证明过程
明确上面几步,我们可以开始求解
第一步 求出每个人最终手中有多少金币,答案就是总金币数/n
第二步 求出每个C
第三部 利用上面的证明结论求出结果
代码:
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;LL A[1000000 + 5];LL C[1000000 + 5];int main(){int n;while(~scanf("%d",&n)){LL m = 0;LL s = 0;for(int i =1;i<=n;i++){scanf("%lld",&A[i]);s += A[i];}m = s / n;C[0] = 0;for(int i = 1;i<n;i++){C[i] = C[i-1] + A[i] - m; //递推求出C }sort(C,C+n);LL x = C[n/2]; //x1的选址 LL ans = 0;for(int i = 0;i<n;i++){ans += abs(x - C[i]); //求出距离 }printf("%lld\n",ans);}}
- Uva 11300
- uva 11300
- UVA 11300
- UVA 11300
- uva 11300
- UVA-11300
- uva 11300
- uva 11300
- uva 11300
- UVa 11300
- UVa 11300
- UVA-11300
- UVa 11300
- uva 11300
- Uva 11300 By ACReaper
- uva 11300 中位数
- UVA 11300 <中位数定理>
- UVA - 11300(问题转换)
- c语言学习 第一次
- RTCP介绍及发送间隔控制
- 什么是sql注入?
- Charles 抓包配置
- EM算法——一步步推导
- UVa 11300
- bootstrap解决图标显示不出来问题,出现GET .woff 404 (Not Found)的问题
- JAVA RMI使用
- java实现链表
- 自定义select-box
- shader中的片元函数与顶点函数
- MINI2440和GQ2440烧录问题
- Tango手机分析 3D点云 室内环境重建
- Singleton 单例模式 -- 饿汉