hdu 2297 Run 半平面交

来源:互联网 发布:淘宝澳洲站 编辑:程序博客网 时间:2024/05/29 18:44

题意:
在一条笔直的路上进行赛跑,给出n个运动员的初始坐标和速度大小,假设所有人都会不停地跑,问有都少人可能在某时刻成为第一。


解:
以初始位置为纵坐标,速度为斜率,构造射线。进行半平面交,每条射线的左方为所求部分,现在要找出所求部分的边缘线。


这里写图片描述


#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<vector>using namespace std;#define all(x) (x).begin(), (x).end()#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)#define mes(a,x,s)  memset(a,x,(s)*sizeof a[0])#define mem(a,x)  memset(a,x,sizeof a)#define ysk(x)  (1<<(x))typedef long long ll;typedef pair<int, int> pii;const int INF =0x3f3f3f3f;const int maxn= 50000    ;const double PI=cos(-1.0);const double eps=1e-10;int dcmp(double x){    if(fabs(x)<eps)  return 0;    else return x<0?-1:1;}struct Point{    double x,y;    Point(double x=0,double y=0):x(x),y(y) {};    bool operator ==(const Point B)const {return dcmp(x-B.x)==0&&dcmp(y-B.y)==0;}    bool operator<(const Point& b)const    {        return dcmp(x-b.x)<0|| dcmp(x-b.x)==0 &&dcmp(y-b.y)<0;    }}poly[maxn+10];typedef Point Vector;Vector operator -(Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y); }double Cross(Vector A,Vector B)//叉乘{    return A.x*B.y-A.y*B.x;}double Dot(Vector A,Vector B)//点乘{    return A.x*B.x+A.y*B.y;}Vector operator +(Vector A,Vector B) {return Vector(A.x+B.x,A.y+B.y); }Vector operator *(Vector A,double p) {return Vector(A.x*p,A.y*p); }Point GetLineIntersection(Point P,Vector v,Point Q,Vector w)//点线式{    Vector u=P-Q;    double t=Cross(w,u)/Cross(v,w);    return P+v*t;}struct Line{    Point p,p2;    Vector v;    double ang;    Line(){}    Line(Point a,Vector v):p(a),v(v){ang=atan2(v.y,v.x); }//点线式    void twoPointIntial(Point p,Point p2)//两点式    {        this->p=p;        this->p2=p2;        v=  p2-p;        ang=atan2(v.y,v.x);    }    bool operator<(const Line & L)const    {        return ang<L.ang;    }}L[maxn+10];typedef Line Seg;Point GetIntersection(Line a,Line b){    Vector u=a.p-b.p;    double t=Cross(b.v,u)/Cross(a.v,b.v);    return a.p+a.v*t;}bool OnLeft(Line L,Point p){    return Cross(L.v,p-L.p)>0;}Point p[maxn+5];Line q[maxn+5];int HalfplaneIntersection(Line* L,int n,Point * poly){    sort(L,L+n);    int first,last;    q[first=last=0]=L[0];    for(int i=1;i<n;i++)    {        while(first<last&&!OnLeft(L[i],p[last-1] ) )  last--;        while(first<last&&!OnLeft(L[i],p[first]))  first++;        q[++last]=L[i];        if(fabs(Cross(q[last].v,q[last-1].v) )<eps )        {            last--;            if(OnLeft(q[last],L[i].p) )  q[last]=L[i];        }        if(first<last) p[last-1]=GetIntersection(q[last-1],q[last] );    }    while(first<last&&!OnLeft(q[first],p[last-1])) last--;    if(last-first<=1)  return 2;    p[last]=GetIntersection(q[last],q[first]);    int m=0;    for(int i=first;i<=last;i++) poly[m++]=p[i];    return m;}int main(){   std::ios::sync_with_stdio(false);   int T,n;cin>>T;   while(T--)   {       cin>>n;       for0(i,n)       {          double p,sp;          cin>>p>>sp;          L[i]=Line(Point(0,p),Vector(1,sp));       }       L[n++].twoPointIntial(Point(0,0),Point(0,-INF));       int m=HalfplaneIntersection(L,n,poly);      printf("%d\n",m-1);   }   return 0;}/*111 1*/

最后减去1,是为了减去新增加的1条边。在此题进行半平面角后的结果集合中,有多少个点正好就对应多少条边。

0 0
原创粉丝点击