题意: 有n个飞机,都有自己的初始位置和行驶方向,问第一次距离小于d的时间,和这两架飞机。
思路:三分+二分
枚举任意两个飞机,在0-INF三分找最近的时间tmp,在0-tmp找距离为d的时间。
#include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <stack> #include <queue> #include <vector> #include <map> #include <string> #define LL long long #define DB double using namespace std; const DB INF = 1e200; const DB EPS = 1e-5; struct cpoint3{ DB x,y,z; void get(){scanf("%lf%lf%lf",&x,&y,&z);} cpoint3(){} cpoint3(DB a,DB b,DB c){x=a,y=b,z=c;} }; struct cvector3{ DB x,y,z; cvector3(){} cvector3(DB a,DB b,DB c){x=a,y=b,z=c;} void get(){scanf("%lf%lf%lf",&x,&y,&z);} }; cvector3 operator*(DB a,cvector3 b) { return cvector3(a*b.x,a*b.y,a*b.z); } cpoint3 operator+(cpoint3 a,cvector3 b) { return cpoint3(a.x+b.x,a.y+b.y,a.z+b.z); } int n; const int N = 509; cpoint3 re[N]; cvector3 rat[N]; DB d; DB dist(cpoint3 a,cpoint3 b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)); } cpoint3 a1,a2; cvector3 v1,v2; DB three(DB l,DB r) { DB mid,mmid; while(r-l>EPS) { mid = (l+r)/2; mmid = (mid+r)/2; DB d1 = dist(a1+mid*v1,a2+mid*v2); DB d2 = dist(a1+mmid*v1,a2+mmid*v2); if(d1<d2) r = mmid; else l = mid; } return l; } DB two(DB l,DB r) { DB mid; while(r-l>EPS) { mid = (l+r)/2; DB d1 = dist(a1+mid*v1,a2+mid*v2)-d; if(d1<0) r = mid; else l = mid; } //cout<<l<<endl; //cout<<dist(a1+l*v1,a2+l*v2)<<"- "<<d+EPS<<endl; if(l<=EPS||dist(a1+l*v1,a2+l*v2)>d*(1+EPS)) return -1; return l; } DB solve(int a,int b) { a1=re[a],a2=re[b]; v1=rat[a],v2=rat[b]; DB tmp = three(-1,1e8); //cout<<tmp<<endl; return two(-1,tmp+EPS); } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif scanf("%d%lf",&n,&d); int a,b;DB t=INF; for(int i=0;i<n;i++) { re[i].get();rat[i].get(); } for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { DB tmp = solve(i,j); // cout<<i+1<<" "<<j+1<<" "<<tmp<<endl; if(tmp>-EPS) { if(t>tmp) { t = tmp; a = i+1,b=j+1; } } } } if(t+EPS>=INF) { printf("OK\n"); }else { printf("ALARM!\n%.9lf %d %d\n",t,a,b); } return 0; }