Uva 11300 Spreading the Wealth(贪心)

Posted new-ljx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Uva 11300 Spreading the Wealth(贪心)相关的知识,希望对你有一定的参考价值。

题目链接: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 imes 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
",ans);
33     }
34     return 0;
35 } 
AC代码

以上是关于Uva 11300 Spreading the Wealth(贪心)的主要内容,如果未能解决你的问题,请参考以下文章

Uva 11300 Spreading the Wealth 中位数

UVA11300 Spreading the Wealth水题

UVa 11300 Spreading the Wealth(有钱同使)

uva 11300 Spreading the Wealth

Uva 11300 Spreading the Wealth(贪心)

UVa11300 - Spreading the Wealth