大致題意:給定 n 個起點的二維坐標和速度的大小和方向;問在哪一時刻所有兩點間的最大距離最小。
// Time 78 ms; Memory 1316K
#include<iostream> #include<cstdio> #include<cmath> #define maxn 50000 #define maxm 305 #define sqr(x) ((x)*(x)) #define eps 1e-5 using namespace std; double a[maxn],b[maxn],c[maxn]; int cas,cnt; int sig(double x) { return (x>eps)-(x<-eps); } typedef struct point { double x,y; point(double xx=0,double yy=0):x(xx),y(yy){} }vector; point pt[maxm]; vector vt[maxm]; vector operator - (point p,point q) { return vector(p.x-q.x,p.y-q.y); } double dot(vector p,vector q) { return p.x*q.x+p.y*q.y; } double cal(double t) { double tmp,res=a[0]*t*t+b[0]*t+c[0]; for(int i=1;i<cnt;i++) { tmp=a[i]*t*t+b[i]*t+c[i]; if(res<tmp) res=tmp; } return res; } int main() { int i,j,t,n; double l,r,m1,m2,tmp; vector v,w; scanf("%d",&t); while(t--) { scanf("%d",&n); cnt=0; l=r=0.0; for(i=0;i<n;i++) scanf("%lf%lf%lf%lf",&pt[i].x,&pt[i].y,&vt[i].x,&vt[i].y); for(i=0;i<n;i++) for(j=i+1;j<n;j++) { v=vt[j]-vt[i], w=pt[j]-pt[i], a[cnt]=dot(v,v), b[cnt]=2*dot(v,w), c[cnt]=dot(w,w); tmp=-b[cnt]/(2*a[cnt]); if(r<tmp) r=tmp; cnt++; } while(sig(r-l)>0) { m1=l+(r-l)/3;m2=r-(r-l)/3; if(cal(m1)<cal(m2)) r=m2; else l=m1; } printf("Case #%d: %.2lf %.2lf\n",++cas,l,sqrt(cal(l))); } return 0; }