CodeForce 204 Div2. C Jeff And Rounding

来源:互联网 发布:六安市数控编程人才网 编辑:程序博客网 时间:2024/05/17 21:26

题目:  有2N个实数,不重复每次选取两个数,一个向下取整,另一个向上取整,  求变化前后和值之差的 最小值。

分析: 这种题没什么特定的算法,比赛时看RP, 不是容易想到方法。

可以这样考虑这个问题,  设实数对应的小数部分为X,  若向下取整 变化量为 -Xi,   若向上取整变化量为 +(1-Xj)  ,总变化量为M*1+Sigma{ X }     [ M是1的个数 ] (当然整数向上取整不变)

惊人的发现小数部分的变化情况都是去负号, 这样我们只需对所有的小数部分求和,为定值,  而决定变化量的是 1 的个数,(只有对非正数向上取整才有1)

比如下面两种情况:

(1)       1.2    2.0    3.0     4.0      (1最多一个,最少零个)

(2)        1.2   2.3     3.4    5.0      (1最多两个,最少一个)

可以得到规律:1的个数总是在某个区间变化,  并可以取其中的任意值。 接下来只需枚举这些可能, 求变化量的最小值即可。


代码:

   #include<iostream>#include<cstdio> #include<cmath>using namespace std;typedef long long LL; const double eps=1e-20;double a[5000]; int main(){ double x,sum=0;int N,cnt=0;cin>>N;for(int i=0;i<N*2;i++){cin>>x;double t=x-floor(x);sum += t;if(t>eps) cnt++;}double ans=1e10;int u,v;if(cnt<=N){u=0;  v=cnt;}else {u=cnt-N;  v=N;}for(int i=u;i<=v;i++){ans=min(ans,abs(i-sum));}printf("%.3f\n",ans); return 0;}


原创粉丝点击