码迷,mamicode.com
首页 > 其他好文 > 详细

Uva 11300 Spreading the Wealth(贪心)

时间:2020-01-23 19:45:44      阅读:67      评论:0      收藏:0      [点我收藏+]

标签:sed   closed   gif   问题   space   print   计算   eof   现在   

题目链接:https://vjudge.net/problem/UVA-11300

 

这道题的思路太神了,但很难想到是贪心。

 

用M表示每个人最终拥有的金币数。

首先假设有四个人。假设1号给2号3枚,2号又给1号5枚,那么实际上1号并没有给2号,而2号给了1号2枚。这样设$x_2$表示2号给了1号$x_2$枚。若$x_2<0$,那么就表示1号给了2号$-x_2$枚。这样我们就相当于在1号和2号之间连了一条边,表示1号2号之间硬币关系(注意是环形,所以$x_1$表示1号和4号之间的硬币关系)。

假设1号原来有$A_1$枚硬币,那么根据1号给了4号$x_1$枚,收到了$x_2$枚硬币,所以现在1号手中有$A_1+x_2-x_1$枚。根据开始的M,我们可以得到:$M=A_1+x_2-x_1$。同理,我们可以得到其他的方程。

得到n-1个方程之后,可以尝试用$x_1$表示其他的$x_i$:

对于第1个人:$M=A_1+x_2-x_1$ --> $x_2=M-A_1+x_1=x_1-C_1$(规定$C_1=A_1-M_1$);

对于第2个人:$M=A_2+x_3-x_2$ --> $x_3=M-A_2+x_2=M-A_2+(M-A_1+x_1)=2\times M-A_1-A_2+x_1=x_1-C_2$

.....

然而对于第n个人,这个式子是多余的——关于n的两个x,已在n-1和1中计算了。

现在我们希望所有$x_i$的绝对值要尽可能地小,即$|x_1|+|x_1-C_1|+\cdots +|x_1-C_{n-1}|$的最小,而它的几何意义便是在数轴上找一个点使得这个点到所有C的距离最短。我们会发现这个点便是这些数的中位数(奇偶都是)。

注意一些边界问题..

(详细证明见 蓝书P5)

 

AC代码:

技术图片
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 
 7 using namespace std;
 8 
 9 const int maxn=1000005;
10 
11 int n;
12 long long mid,ans,sum,M;
13 long long A[maxn],C[maxn];
14 
15 inline void init(){
16     memset(A,0,sizeof(A));
17     sum=ans=0;
18 }
19 
20 int main(){
21     while(scanf("%d",&n)!=EOF){
22         init();
23         for(int i=1;i<=n;i++){
24             scanf("%lld",&A[i]);
25             sum+=A[i];
26         }
27         M=sum/n;
28         for(int i=1;i<n;i++) C[i]=C[i-1]+A[i]-M;
29         sort(C,C+n);
30         mid=C[n/2];
31         for(int i=0;i<n;i++) ans+=abs(C[i]-mid);
32         printf("%lld\n",ans);
33     }
34     return 0;
35 } 
AC代码

Uva 11300 Spreading the Wealth(贪心)

标签:sed   closed   gif   问题   space   print   计算   eof   现在   

原文地址:https://www.cnblogs.com/New-ljx/p/12230930.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!