hdu4717 The Moving Points 三分法

题意:坐标系上有n个点,每个点的坐标和移动方向速度告诉你,速度方向都是固定的。然后要求一个时刻,使得这个时刻,这些点中最远的距离最小。

做法:三分法,比赛的时候想不到。考虑两个点,如果它们走出来的路径能在一定时间后相交的话,那么它们之间的距离肯定是先减小后增大,这样其实可以写成一个二次函数(开口朝下),然后考虑所有的点对之间的最远点,就是对所有的二次函数取一个最大值,嗯,好像还是个二次函数,呃,乱想的,想不下去了。

比赛时候想到可能是单调的或者单峰的,现在还是有点想不通,求解答。

#define maxn 403

const double eps = 1e-5;

double x[maxn],y[maxn];
double xi[maxn],yi[maxn];
double tx[maxn],ty[maxn];
double _max ;
double tmp;
int n ;
double dist(double x ,double y ,double xx , double yy )
{
  return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
}
double calc(double t)
{
  for(int i = 1; i <= n ; i ++ )
  {
    tx[i] = x[i] + xi[i] * t ;
    ty[i] = y[i] + yi[i] * t ;
  }
  _max = 0;
  for(int i =1 ; i <= n ; i ++ )
  {
    for(int j= i + 1; j <= n ; j ++ )
    {
      _max = max(_max , dist(tx[i],ty[i],tx[j],ty[j]));
    }
  }
  return _max;
}
void Solve()
{
  double Left, Right;
  double mid, midmid;
  double mid_area, midmid_area;
  Left = 0.0;
  Right = 21000000.0;
  while (Left + eps < Right)
  {
    mid = (Left + Right) / 2;
    midmid = (mid + Right) / 2;
    mid_area = calc(mid);
    midmid_area = calc(midmid);
    // 假设求解最大极值.
    if (mid_area <= midmid_area) Right = midmid;
    else Left = mid;
  }
  printf("%.2lf %.2lf
",Left,midmid_area);
}


int main()
{
  int cas;
  int cast = 0 ;
  scanf("%d",&cas);
  while(cas -- )
  {
    scanf("%d",&n);
    for(int i = 1; i <= n ; i ++ )
    {
      scanf("%lf%lf%lf%lf",&x[i],&y[i],&xi[i],&yi[i]);
    }
    printf("Case #%d: ", ++ cast);
    Solve();
  }
  return 0;
}
View Code
原文地址:https://www.cnblogs.com/jh818012/p/3315516.html