Polygons

/*

题意:判断一个顺时针凸包A是否包含(不包括边界)简单多边形B

分析:判断B的每个点是否在A内; 因为n是1e5,m是1e4,如果判断算法在log(m)数量级左右, O(n * Olog(m) )可以过

*/

#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <queue>
#include <deque>

#define MAX 200005
#define INF 1e8
#define FOR(i, n) for(int i  = 0; i < n; i++)
#define FORB(i, n) for(int i = n - 1; i >= 0; i--)
#define MP(i, j) make_pair(i, j)
#define MEM(array, val) memset(array, val, sizeof(array))
#define pu first
#define pv second
#define eps 1e-50
#define INF 1e50
using namespace std;
inline int cmpd(double x){ return x > eps ? 1 : ( x < - eps ? - 1 : 0); }
inline double sqr(double x){ return x * x;}
inline bool zero(double x){return cmpd(x) == 0;}
int sgn(double x){ return x > eps ? 1 : (x < -eps? -1 : 0); }
struct Point{
    double x, y;
    Point(){}
    Point(const  double &xx, const double &yy):x(xx), y(yy){}
    Point operator - (const Point &a)const{
        return Point(x - a.x, y - a.y);
    }
    Point operator + (const Point &a)const{
        return Point(x + a.x, y + a.y);
    }
    Point operator / (const double &w)const {
        return Point(x / w, y / w);
    }
    friend double dot(const Point &a, const Point &b){
        return a.x *b.x + a.y * b.y;
    }
    friend double det(const Point &a, const Point &b){
        return a.x * b.y - a.y * b.x;
    }
    void in(){
        scanf("%lf %lf",&x, &y);
    }
    void out(){
        printf("%.2f  %.2f\n", x, y);
    }
};

struct Poly{
    vector<Point>p;
    Poly(){}
    bool isContain(const Point &t){
        int n = p.size();
        Point g = (p[0] + p[n/3] + p[n * 2 / 3]) / 3.0;
        int r = n, l = 0;
        while(l + 1 < r){
            int mid = (l + r)>> 1;
            int k =  sgn(det(p[l] - g, p[mid] - g) );
            int resl =  sgn( det(p[l] - g, t - g) );
            int resm = sgn(det(p[mid] - g, t - g) );
            if(k < 0){
                if(resl <= 0 && resm > 0){
                    r = mid;
                }else{
                    l = mid;
                }
            }else {
                if(resl > 0 && resm <= 0){
                    l  = mid;
                }else {
                    r = mid;
                }
            }
        }
        r %= n;
        int z = sgn( det(p[r] - t, p[l] - t) );
//        cout<<z<<endl;
        if(z == 1){
            return true;
        }
        return false;
    }
}A;
int n, m;
int main(){
    cin>>n;
    Point tt;
    FOR(i, n){
        tt.in();
        A.p.push_back(tt);//顺时针严格凸包
    }
    bool isInSide = true;
    cin>>m;
    FOR(j, m){
        tt.in();
        if(isInSide == true && !A.isContain(tt)){
            isInSide= false;
        }
    }
    if(isInSide){
        puts("YES");
    }else {
        puts("NO");
    }
    return 0;
}
/*
6 -2 1 0 3 3 3 4 1 3 -2 2 -2 4 0 1 2 2 3 1 1 0
5 1 2 4 2 3 -3 -2 -2 -2 1 4 0 1 1 2 4 1 2 -1
5 -1 2 2 3 4 1 3 -2 0 -3 5 1 0 1 1 3 1 5 -1 2 -1
*/


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值