1. 程式人生 > >HDU 4717 The Moving Points (三分 模板)

HDU 4717 The Moving Points (三分 模板)

There are N points in total. Every point moves in certain direction and certain speed. We want to know at what time that the largest distance between any two points would be minimum. And also, we require you to calculate that minimum distance. We guarantee that no two points will move in exactly same speed and direction.
Input
The rst line has a number T (T <= 10) , indicating the number of test cases. 
For each test case, first line has a single number N (N <= 300), which is the number of points. 
For next N lines, each come with four integers X i, Y i, VX i and VY i (-10 6 <= X i, Y i <= 10 6, -10 2 <= VX i , VY i <= 10 2), (X i, Y i) is the position of the i th point, and (VX i , VY i) is its speed with direction. That is to say, after 1 second, this point will move to (X i + VX i , Y i + VY i).
Output
For test case X, output "Case #X: " first, then output two numbers, rounded to 0.01, as the answer of time and distance.
Sample Input
2
2
0 0 1 0
2 0 -1 0
2
0 0 1 0
2 1 -1 0
Sample Output
Case #1: 1.00 0.00
Case #2: 1.00 1.00

題意:給定n個點,然後這些點朝著給定的方向和給定速度走,在某個時間後,點停下來,可以求得此時任意兩點之間的最大距離。問何時停止可以使得任意兩點之間的最大距離最小。

思路:三分時間,判斷條件是求出時間的情況下,任意兩點之間的最大距離就好了。

三分:時間。

建構函式:運動之間的兩點間的距離為先減小後增大(包含部分特殊的運動,比如速度相同,或者當前兩點的距離已經為最小,之後變大。都在三分法的考慮範圍之內)

所以建構函式為a>0,凸函式

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdio>
#include <functional> //小根堆特有標頭檔案
typedef long long ll;
using namespace std;
const double eps=1e-8;  
const int N=330;  
int n;  
double x[N],y[N],vx[N],vy[N];  
double cal(double t)  
{  
    double ret=0;  
    for(int i=0;i<n;i++)  
        for(int j=i+1;j<n;j++)  
        {  
            double x1=x[i]+vx[i]*t;  
            double y1=y[i]+vy[i]*t;  
            double x2=x[j]+vx[j]*t;  
            double y2=y[j]+vy[j]*t;  
            ret=max(ret,sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));  
        }  
        return ret;  
  
}  
double solve()  
{  
    double l=0,r=1e10;  
    while(r-l>=eps)  
    {  
        double mid1=(l+r)/2;  
        double mid2=(mid1+r)/2;  
        if(cal(mid1)>=cal(mid2))  
            l=mid1;  
        else  
            r=mid2;  
    }  
    return l;  
}  
int main()  
{  
   int icase,T=1;  
   scanf("%d",&icase);  
   while(icase--)  
   {  
       scanf("%d",&n);  
       for(int i=0;i<n;i++)  
        scanf("%lf%lf%lf%lf",&x[i],&y[i],&vx[i],&vy[i]);  
       double t=solve();  
       printf("Case #%d: %.2lf %.2lf\n",T++,t,cal(t));  
   }  
   return 0;  
}