关于二分精度问题

 

例题: cf782B

 

提议:在数轴x上给n个点的位置,每个点都有一个最大的移动速度,方向任意。在数轴x上找一个点c,使得这n个点到点c的最大时间最小,输出最小时间,误差 <= 0.000001。

 

思路:定义L = 0, R= Max, 二分点c的位置,然后对于每个位置,check一下;

 

初解:

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;

const int MAXN = 6e4 + 5;
const double Min = 0.0000001;

double s[MAXN + 5], v[MAXN + 5];
int n;

int check(double ans)
{
double Max_L = 0, Max_R = 0;
for(int i = 1; i <= n; i++){
if(s[i] > ans){
double x = (s[i] - ans) / v[i];
Max_R = max(Max_R, x);
}
else if(s[i] < ans){
double x = (ans - s[i]) / v[i];
Max_L = max(Max_L, x);
}
}
if(Max_R > Max_L) return 1;
return 0;
}

void find(double L, double R)
{
while(R - L >= Min){                                //当R -  L >= Min即进行二分,结果T在了test21, 正解是强行二分100次(即在考虑精度的二分题目中尽量用强制二分n次来保证精度)
double mid = (R + L) / 2;
int k = check(mid);
if(k == 1) L = mid;
else R = mid;
sum++;
}
double Max = 0;
for(int i = 1; i <= n; i++){
if(s[i] > L){
double x = (s[i] - L) / v[i];
Max = max(Max, x);
}
else{
double x = (L - s[i]) / v[i];
Max = max(x, Max);
}
}
printf("%lf\n", Max);
}

int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%lf", &s[i]);
for(int i = 1; i <= n; i++) scanf("%lf", &v[i]);
double L = 1, R = 1000000000;
find(L, R);
}

posted @ 2017-03-06 21:03  _Pain  阅读(190)  评论(0)    收藏  举报