foj 2144 三位几何+区间覆盖

题目大意:一个人站在三维坐标系下的原点处用炮打蚊子,给出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;
}
原文地址:https://www.cnblogs.com/xiong-/p/3601169.html