天天看點

CodeForce 204 Div2. C Jeff And Rounding

題目:  有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;
}