SCUT - 244 - 全新的游戏 - 凸包

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)\n",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\n",area);

        int m;
        scanf("%d",&m);
        while(m--){
            double x,y;
            scanf("%lf%lf",&x,&y);
            if(inside(Point(x,y))){
                printf("Yes\n");
            }
            else{
                printf("No\n");
            }
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/Yinku/p/10403752.html
今日推荐