• UVALive 7281 Saint John Festival (凸包+O(logn)判断点在凸多边形内)


    Saint John Festival

    题目链接:

    http://acm.hust.edu.cn/vjudge/contest/127406#problem/J

    Description

    ``` Porto’s Festa de São João is one of Europe’s liveliest street festivals. Its peak is the night of 23rd to 24th of June, with dancing parties from Ribeira to Foz all night long. Time to celebrate, with friends, relatives, neighbours or simply with other people in streets, armed with colored plastic hammers, huge garlic flowers or a bunch of lemongrass to gently greet passers-by. Fireworks, grilled sardines, barbecues, bonfires, potted basil plants (manjericos) and the sky covered by incandescent sky lanterns (balões de S.João) launched from every corner make this party unique. The sky lanterns are made of thin paper and cannot be released until they are filled in with hot air. Sometimes they burn out still on ground or on the way up, if a sudden gust of wind catches them. For this reason, the successful launchers usually follow the movement of their sky lanterns, with a mixture of anxiety and joy, for as long as they can distinguish them in the sky. We are not aware of any attempt to achieve a Guinness record of sky lanterns launched simultaneously (it could be dreadful night for firemen if there were). Can you imagine, thousands of people preparing their sky lanterns for release at the city park, within a region of larger ones that will be launched simultaneously? The large sky lanterns can be used to identify their positions in the sky afterwards, in order to count the surviving ones at an observation instant. Given the positions of the large sky lanterns and the positions of the small ones, determine the number of small sky lanterns that are in the interior or on the boundary of some triangle defined by any three of the large ones. ```

    Input

    The input file contains several test cases, each of them as described below. The first line has an integer L that defines the number of the large sky lanterns at the observation instant. Each of the following L lines contains a pair of integers separated by a space that gives the coordinates (x, y) of a large sky lantern. After that, there is a line with an integer S that defines the number of small sky lanterns and S lines, each defining the position of a small sky lantern. The height is irrelevant for us. All the given points are distinct and there are at least three points representing large sky lanterns that are not collinear.

    Output

    For each test case, the output has a single line with the number of small sky lanterns that are in the interior or on the boundary of some triangle defined by any three of the large sky lanterns. Constraints: 3 ≤ L ≤ 10 000 Number of large sky lanterns. 1 ≤ S ≤ 50 000 Number of small sky lanterns. 0 ≤ x, y ≤ 2 30 Bounds for coordinates. Note: The picture on the right illustrates the sample input below

    Sample Input

    8 3 4 2 8 5 4 1 8 4 7 3 10 11 2 7 3 6 5 12 3 7 3 3 4 5 0 4 2 6

    Sample Output

    3
    ##题意: 在平面上给出若干个"大点"和"小点". 求有多少个小点满足:在任一由三个大点组成的三角形的内部或边界上.
    ##题解: 看图很容易看出要求一个凸包(证明也很容易). 然后依次判断各点是否在凸包内或边界上. 需要注意的是: 用longlong代替double参与运算,避免精度误差. 由于数据规模的限制,判断点是否在凸多边形内时要用O(logn)的算法. 以下代码用了二分法.
    ##代码: ``` cpp #include #include #include #include #include #include #include #include #include #include #include #define LL long long #define eps 1e-8 #define double LL #define maxn 101000 #define mod 100000007 #define inf 0x3f3f3f3f #define mid(a,b) ((a+b)>>1) #define IN freopen("in.txt","r",stdin); using namespace std;

    struct Point{
    double x,y;
    Point(){}
    Point(double tx,double ty) {x=tx;y=ty;}
    // bool operator<(const Point& b)const
    // {
    // if(x==b.x) return y<b.y;
    // return x<b.x;
    // }
    };

    int sign(double x)
    {
    //if(fabs(x)<eps) return 0;
    if(x == 0) return 0;
    return x<0? -1:1;
    }

    double dmul(Point p0,Point p1,Point p2)
    {return (p1.x-p0.x)(p2.x-p0.x)+(p1.y-p0.y)(p2.y-p0.y);}

    /x>0逆时针 x<0顺时针 x=0三点共线 考虑精度/
    double xmul(Point p0,Point p1,Point p2)
    {return (p1.x-p0.x)(p2.y-p0.y)-(p2.x-p0.x)(p1.y-p0.y);}

    /求两点间距离/
    double Distance(Point p1,Point p2)
    {
    return sqrt((p1.x-p2.x)(p1.x-p2.x)+(p1.y-p2.y)(p1.y-p2.y));
    }

    int n,m;
    Point points[11000];
    int _stack[11000],top; /_stack保存凸包构成点,逆时针/

    int cmp_with_polar(Point p1,Point p2)
    {
    double tmp=xmul(points[0],p1,p2);
    if(sign(tmp)>0) return 1;
    else if(sign(tmp)==0&&sign(Distance(points[0],p1)-Distance(points[0],p2))<0)
    return 1;
    else return 0;
    }

    void polar_sort(int n)
    {
    int pos=0;
    Point p0;
    p0.x=points[0].x;p0.y=points[0].y;

    for(int i=1;i<n;i++){
        if(sign(p0.y-points[i].y)>0||(sign(p0.y-points[i].y)==0&&sign(p0.x-points[i].x)>0)){
            p0.x=points[i].x;
            p0.y=points[i].y;
            pos=i;
        }
    }
    points[pos]=points[0];
    points[0]=p0;
    
    sort(points+1,points+n,cmp_with_polar);
    

    }
    void ConvexHull_Graham(int n) /最终凸包点为_stack[0]~_stack[top-1],共top个/
    {
    polar_sort(n);
    top=0;
    for(int i=0;i<n;i++){
    while(top>1&&sign(xmul(points[_stack[top-2]],points[_stack[top-1]],points[i]))<=0) top--;
    _stack[top++]=i;
    }
    }

    double cross(Point p0, Point p1, Point p2)
    {
    return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
    }

    /二分法判断点是否在凸多边形内(或边界上)/
    bool is_in(int index[], int n, Point p) {
    int l=1, r=n-2,mid;
    while(l<=r) {
    mid = (l+r) >> 1;
    double a1 = xmul(points[index[0]], points[index[mid]], p);
    double a2 = xmul(points[index[0]], points[index[mid+1]], p);
    if(sign(a1)>=0 && sign(a2)<=0) {
    if(sign(xmul(points[index[mid]], points[index[mid+1]], p)) >= 0) return 1;
    return 0;
    } else if(sign(a1) < 0) {
    r = mid -1;
    } else {
    l = mid+1;
    }
    }
    return 0;
    }

    int main(int argc, char const *argv[])
    {
    //IN;

    int n, m;
    while(scanf("%d", &n) != EOF)
    {
        for(int i=0; i<n; i++) {
            scanf("%I64d %I64d", &points[i].x,&points[i].y);
        }
        ConvexHull_Graham(n);
    
        //for(int i=0; i<top; i++)
        //    printf("%I64d %I64d
    ", points[_stack[i]].x, points[_stack[i]].y);
    
        scanf("%d", &m);
        int ans = 0;
        while(m--) {
            Point cur;
            scanf("%I64d %I64d", &cur.x,&cur.y);
            if(is_in(_stack, top, cur)) ans++;
        }
    
        printf("%d
    ", ans);
    }
    
    return 0;
    

    }

  • 相关阅读:
    SecureCRT
    NFS服务器搭建
    卸载oracle步骤
    redhat 5.5 x86_x64搭建samba服务器
    ORA-01940: cannot drop a user that is currently connected
    迁移表空间
    日常SQL使用总结
    DataGuard常规操作命令
    使用PowerDesginer画ER图
    数据库卸载
  • 原文地址:https://www.cnblogs.com/Sunshine-tcf/p/5769091.html
Copyright © 2020-2023  润新知