ZOJ 1081 Points Within (几何)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1081

有一些经常用的几何知识,留着备用!

#include"iostream"
#include"string"
#include"cstdio"
#include"algorithm"
#include"cmath"
#define E 1e-8
#define MAX 1e5
#define N 99
using namespace std;
struct Point   /*定义点*/
{
    double x, y;
};
struct Segment   /*定义线段*/
{
    Point a, b;
};


double min(double x, double y)
{
    return x > y ? y : x;
}


double max(double x, double y)
{
    return x > y ? x : y;
}


double xmult(Point p1, Point p2, Point p0)    /*计算两向量的叉积*/
{
    return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}


bool is_online(Point p, Segment s) /*判断p是否在线段s上*/
{
    if(fabs(xmult(s.a, p, s.b)) <= E && min(s.a.x, s.b.x) <= p.x &&
            p.x <= max(s.a.x, s.b.x) && min(s.a.y, s.b.y) <= p.y && p.y <= max(s.a.y, s.b.y))
        return true;
    return false;

}


bool is_segment_crossing(Segment u, Segment v) /*判断两线段是否相交*/
{
    return((max(u.a.x, u.b.x) >= min(v.a.x, v.b.x)) &&
           (max(v.a.x, v.b.x) >= min(u.a.x, u.b.x)) &&
           (max(u.a.y, u.b.y) >= min(v.a.y, v.b.y)) &&
           (max(v.a.y, v.b.y) >= min(u.a.y, u.b.y)) &&
           (xmult(v.a, u.b, u.a) * xmult(u.b, v.b, u.a) >= 0) &&
           (xmult(u.a, v.b, v.a) * xmult(v.b, u.b, v.a) >= 0));

}
bool is_in_area(Point p, Point s[], int len) /*判断点p是否在以边点顺序排列的点集s所围成的多边形内*/
{
    Segment seg;
    Segment pp;
    int num = 0;
    Point MM;/*定义无穷点*/
    MM.y = p.y;
    MM.x = MAX;
    pp.a = p;
    pp.b = MM; /*构造一条平行于x轴的以p为端点的右射线pp*/
    for(int i = 0; i < len; i++)
    {
        seg.a = s[i];
        seg.b = s[(i+1)%len];
        if(is_online(p, seg)) /*点p在边上*/
            return true;
        if(fabs(seg.a.y - seg.b.y) < E) /*水平*/
            continue;
        if(is_online(seg.a, pp)) /*边的一端点在射线上*/
        {
            if(seg.a.y > seg.b.y)
                num++;
        }
        else if(is_online(seg.b, pp))
        {
            if(seg.b.y > seg.a.y)
                num++;
        }
        else if(is_segment_crossing(pp, seg))
            num++;
    }
    //cout<<num<<"::"<<endl;
    if(num % 2 == 1)
        return true;
    return false;
}


int main()
{
    int n;
    Point s[N];
    int pId = 0;
    while(true)
    {
        scanf("%d", &n);
        if(n == 0)
            break;
        int t;
        scanf("%d", &t);
        for(int i = 0; i < n; i++)
        {
            scanf("%lf%lf", &s[i].x, &s[i].y);
        }
        if(pId > 0)
            printf("\n");
        printf("Problem %d:\n", pId + 1);
        for(int i = 0; i < t; i++)
        {
            Point p;
            cin >> p.x >> p.y;
            if(is_in_area(p, s, n))
                printf("Within\n");
            else
                printf("Outside\n");
        }
        pId++;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值