2013杭电 warm 2, hdu 4717 The Moving Points 三分
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4717
第一次写三分,这个解法是学解题报告的,感谢原作者。
首先对每对点对,他们的距离关于时间t是二次函数,现在就是求c[n][2] 个二次函数,每个点取最大值构成的函数的极值。
由于每个子函数都是先减后增,或者对称轴小于0,直接单增,他们的max一定也保持着这个性质 (具体证明和n个下凸函数max还是下凸函数很像?)
然后取100次精度就够了
代码:
#include<iostream> #include<cstdio> #include<cmath> using namespace std; int x[300],y[300],vx[300],vy[300]; int n; double f(double t) { double max=0; for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) { double cur=(x[i]+t*vx[i]-x[j]-t*vx[j])*(x[i]+t*vx[i]-x[j]-t*vx[j])+(y[i]+t*vy[i]-y[j]-t*vy[j])*(y[i]+t*vy[i]-y[j]-t*vy[j]); if(cur>max) max=cur; } return max; } int main() { int T; cin>>T; int index=0; while(T--) { cin>>n; for(int i=0;i<n;i++) scanf("%d%d%d%d",&x[i],&y[i],&vx[i],&vy[i]); double l=0,r=100000000,m1,m2; for(int i=0;i<100;i++) { m1=l+(r-l)/3; m2=r-(r-l)/3; if(f(m1)<f(m2)) r=m2; else l=m1; } double ans=sqrt(f(l)); printf("Case #%d: %.2lf %.2lf\n",++index,l,ans); } }