题意:在一维坐标轴上,给定n个点的坐标以及他们的最大移动速度,问他们能聚到某一点处的最短时间。
分析:
1、二分枚举最短时间即可。
2、通过检查当前时间下,各点的最大移动范围之间是否有交集,不断缩小搜索范围。
3、相当于二分枚举找右临界线,符合要求的点都在右边。
4、通过给二分一个查找次数的上界,eg:k=200,而不是dcmp(l, r)<=0,后者会tle。
5、检查是否有交集,就是以第一个点的最大移动区间为标准,不断与其他区间取交集并更新再继续比较。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<stack> #include<deque> #include<queue> #include<list> #define lowbit(x) (x & (-x)) const double eps = 1e-8; inline int dcmp(double a, double b){ if(fabs(a - b) < eps) return 0; return a > b ? 1 : -1; } typedef long long LL; typedef unsigned long long ULL; const int INT_INF = 0x3f3f3f3f; const int INT_M_INF = 0x7f7f7f7f; const LL LL_INF = 0x3f3f3f3f3f3f3f3f; const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f; const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; const int MOD = 1e9 + 7; const double pi = acos(-1.0); const int MAXN = 60000 + 10; const int MAXT = 10000 + 10; using namespace std; int a[MAXN], v[MAXN]; int n; bool judge(double t){ double tmpl = (double)a[0] - (double)v[0] * t; double tmpr = (double)a[0] + (double)v[0] * t; for(int i = 1; i < n; ++i){ double l = (double)a[i] - (double)v[i] * t; double r = (double)a[i] + (double)v[i] * t; if(dcmp(tmpl, r) > 0 || dcmp(tmpr, l) < 0) return false; if(dcmp(l, tmpl) > 0) tmpl = l; if(dcmp(r, tmpr) < 0) tmpr = r; } return true; } double solve(){ double l = 0, r = (double)1e9; int k = 200; while(k--){ double mid = (l + r) / 2; if(judge(mid)) r = mid; else l = mid + eps; } return r; } int main(){; scanf("%d", &n); for(int i = 0; i < n; ++i){ scanf("%d", &a[i]); } for(int i = 0; i < n; ++i){ scanf("%d", &v[i]); } printf("%.12lf ", solve()); return 0; }