zoukankan      html  css  js  c++  java
  • SCUT

    https://scut.online/p/244

    除了常规的求凸包求面积,还有一个判断点在凸包内,先找出点所在的三角扇区。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    
    
    /****************************凸包模板*******************************/
    
    const double eps = 1e-6;
    
    int sgn(double x) {
        if(fabs(x) < eps)
            return 0;
        if(x < 0)
            return -1;
        else
            return 1;
    }
    
    struct Point {
        double x,y;
        Point() {}
        Point(double _x,double _y) {
            x = _x;
            y = _y;
        }
    
        Point operator -(const Point &b)const {
            return Point(x - b.x,y - b.y);
        }
    
        //叉积
        double operator ^(const Point &b)const {
            return x*b.y - y*b.x;
        }
    
        //点积
        double operator *(const Point &b)const {
            return x*b.x + y*b.y;
        }
    
        void input() {
            scanf("%lf%lf",&x,&y);
        }
    
        void output() {
            printf("(%.2f,%.2f)
    ",x,y);
        }
    
    };
    
    struct Line {
    
        Point s,e;
    
        Line() {}
    
        Line(Point _s,Point _e) {
    
            s = _s;
            e = _e;
    
        }
    
    };
    
    //*两点间距离
    
    double dist(Point a,Point b) {
    
        return sqrt((a-b)*(a-b));
    
    }
    
    /*
    
    * 求凸包,Graham算法
    
    * 点的编号0~n-1
    
    * 返回凸包结果Stack[0~top-1]为凸包的编号
    
    */
    
    const int MAXN = 100000+5;
    
    Point List[MAXN];
    
    int Stack[MAXN];//用来存放凸包的点
    
    int top;//表示凸包中点的个数
    
    //相对于List[0]的极角排序
    
    bool _cmp(Point p1,Point p2) {
        double tmp = (p1-List[0])^(p2-List[0]);
        if(sgn(tmp) > 0)
            return true;
        else if(sgn(tmp) == 0 && sgn(dist(p1,List[0]) - dist(p2,List[0])) <= 0)
            return true;
        else
            return false;
    }
    
    Point p[MAXN];
    
    void Graham(int n) {
        Point p0;
        int k = 0;
        p0 = List[0];
        //找最下边的一个点
        for(int i = 1; i < n; i++) {
            if((p0.y>List[i].y) || (p0.y == List[i].y && p0.x > List[i].x) ) {
                p0 = List[i];
                k = i;
            }
        }
        swap(List[k],List[0]);
        sort(List+1,List+n,_cmp);
        if(n == 1) {
            top = 1;
            Stack[0] = 0;
            return;
        }
        if(n == 2) {
            top = 2;
            Stack[0] = 0;
            Stack[1] = 1;
            return ;
        }
        Stack[0] = 0;
        Stack[1] = 1;
        top = 2;
        for(int i = 2; i < n; i++) {
            while(top > 1 && sgn((List[Stack[top-1]]-List[Stack[top-2]])^(List[i]-List[Stack[top-2]])) <= 0)
                top--;
            Stack[top++] = i;
        }
    
        for(int i=0;i<top;i++){
            p[i]=List[Stack[i]];
        }
    }
    
    
    bool inside(Point A) {
        int l=1,r=top-2,mid;
        while(l<=r) {
            mid=(l+r)>>1;
            double a1=(p[mid]-p[0])^(A-p[0]);
            double a2=(p[mid+1]-p[0])^(A-p[0]);
            if(sgn(a1)>=0&&sgn(a2)<=0) {
                if(sgn((p[mid+1]-p[mid])^(A-p[mid]))>=0)
                    return true;
                return false;
            }
            else if(a1<0) {
                r=mid-1;
            }
            else {
                l=mid+1;
            }
        }
        return false;
    }
    /****************************凸包模板*******************************/
    int main() {
        int n;
        while(~scanf("%d",&n)){
            double x,y;
            for(int i=0;i<n;i++) {
                scanf("%lf%lf",&x,&y);
                List[i].x=x;
                List[i].y=y;
            }
            Graham(n);
            /*for(int i=0; i<top; i++) {
                List[Stack[i]].output();
            }*/
    
            double area=0.0;
            Point o(0,0);
            for(int i=0; i<top; i++) {
                area+=(List[Stack[i]]-o)^(List[Stack[(i+top-1)%top]]-o);
            }
    
            area*=0.5;
            area=fabs(area);
    
            printf("%.6f
    ",area);
    
            int m;
            scanf("%d",&m);
            while(m--){
                double x,y;
                scanf("%lf%lf",&x,&y);
                if(inside(Point(x,y))){
                    printf("Yes
    ");
                }
                else{
                    printf("No
    ");
                }
            }
        }
    }
  • 相关阅读:
    前端js部分面试题
    前端css部分面试笔试题
    javascript 面向对象
    string 对象
    JavaScript 正则表达式
    JavaScirpt 位运算
    JavaScript冒泡循环排序案例
    JavaScript 练习题
    浏览器缓存机制
    浏览器对象模型(BOM)
  • 原文地址:https://www.cnblogs.com/Yinku/p/10403752.html
Copyright © 2011-2022 走看看