题目大意:一个人站在三维坐标系下的原点处用炮打蚊子,给出n个蚊子的起始坐标跟单位时间匀速移动的方向向量,距离他R以内的蚊子都可以打到,不过他也需要休息,没蚊子的时候也可以休息下。求他要起来多少次打蚊子。
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; const int N = 100005; const double eps = 1e-6; const double Pi=acos(-1.0); int n, cnt; double R; inline bool scan_d(double &ret) { //如果数据比较多,而输入的数值比较小就不用scanf而用这种输入方法,用scanf会超时 char c; int sgn; if(c = getchar(),c == EOF) return 0; //EOF while(c != '-' && (c < '0' || c > '9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret *= sgn; return 1; } struct Point3 { double x, y, z; Point3(double x=0,double y=0,double z=0):x(x),y(y),z(z){} void get() { scan_d(x); scan_d(y); scan_d(z); } }; struct Node { double x, y; }f[N]; double Dot(Point3 a,Point3 b){return a.x*b.x+a.y*b.y+a.z*b.z;} inline double min(double a,double b){ return a-b>eps?b:a;} inline double max(double a,double b){ return a-b>eps?a:b;} void Deal(Point3 p, Point3 q) { double a=Dot(q,q); double b=2*Dot(p,q); double c =Dot(p,p)-R*R; double t =b*b-4*a*c; if (t < eps) return; else if (fabs(t) < eps) { double i = -b / (2.0 * a); if (i < 0) return; f[cnt].x = f[cnt].y = i; } else { double i = (-b + sqrt(t) ) / (2 * a); double j = (-b - sqrt(t) ) / (2 * a); if (i < -eps && j < -eps) return; else if (i < -eps) i = 0; else if (j < -eps) j = 0; f[cnt].x = min(i, j); f[cnt].y = max(i, j); } cnt++; } void Init() { cnt = 0; Point3 p, v; scanf("%d%lf", &n, &R); for (int i = 0; i < n; i++) { p.get();v.get(); Deal(p, v); } } bool mycomp(const Node &a, const Node &b) { if (fabs(a.y - b.y) > eps) return a.y - b.y < eps; return a.x - b.x < eps; } int Solve() { int i,ans = 0; double start = -1; for (i = 0; i < cnt; i++) { if (f[i].x - start > eps) { start = f[i].y; ans++; } } return ans; } int main () { int i,Icas; scanf("%d", &Icas); for (i = 1; i <= Icas; i++) { Init(); sort(f, f + cnt, mycomp); printf("Case %d: %d %d ", i, cnt, Solve()); } return 0; }