- 时间:2016-03-05 12:06:59 星期六
- 题目编号: UVALive 4504 B - Trick or Treat
- 题目大意:给定坐标轴上若干个点,每个点上有一个人,求x轴上一点,使得所有人到这个点集合所花费的时间最短,所有人同时出发,
- 输入:
- 若干组数据,0结束
- 每组数据
- n顶点个数
- 接下来n行,每个顶点的坐标 double 类型
- 输出:点的坐标,需要的时间
- 分析:可以看出,x轴上从左到最优点,到右, 花费的时间 先降低后升高,那么就可以3分坐标点,求出最优的答案
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; typedef long long LL; #define CLR(x,y) memset((x),(y),sizeof((x))) const int maxn = 50000 + 100; int n; struct Point{ double x,y; bool operator < (const Point a)const { return a.x > x; } }p[maxn]; double Calc(double x) { double rtn = 0; for(int i = 0 ; i < n ;++i){ rtn = max(rtn , sqrt(double(p[i].y * p[i].y + (p[i].x - x) * (p[i].x - x)))); } return rtn; } double Solve(double MIN, double MAX) { double Left, Right; double mid = 0, midmid = 0; double mid_area = 0, midmid_area = 0; Left = MIN; Right = MAX; for(int i = 0;i < 150;++i){ mid = (Left + Right) / 2; midmid = (mid + Right) / 2; mid_area = Calc(mid); midmid_area = Calc(midmid); if (midmid_area - mid_area > eps) Right = midmid; else Left = mid; } return midmid; } int main(){ while(~scanf("%d",&n) && n){ for(int i = 0;i < n ;++i) scanf("%lf%lf",&p[i].x,&p[i].y); sort(p,p+n); double res = Solve(p[0].x,p[n - 1].x); printf("%.7lf %.7lf\n",res,Calc(res)); } return 0; } |