HRBUST 1429凸多边形 计算几何

凸多边形
Time Limit: 2000 MSMemory Limit: 65536 K
Total Submit: 367(87 users)Total Accepted: 117(66 users)Rating: Special Judge: No
Description

已知一个凸多边形A(包含n个点,点按照顺时针给出),和一个点集B(包含m个点),请判断这m个点是否都严格在凸多边形A内部。

Input

输入包含多组测试数据。

对于每组测试数据:

1行,包含一个整数n (3 ≤ n ≤ 105)代表着凸多边形A的点的数量。

接下来n行每行包含一个坐标(x, y) (-109 ≤ x, y ≤ 109表示这个凸多边形,点按照顺时针给出。

n + 2行,包含一个整数m (3 ≤ m ≤ 105)代表着点集B的点的数量。

接下来m行每行包含一个坐标(x, y) (-109 ≤ x, y ≤ 109表示这个点集B

处理到文件结束

Output

对于每组测试数据:

1行,如果点集B都严格在凸多边形A内,输出YES,否则输出NO

Sample Input

4

-10 -10

-10 10

10 10

10 -10

3

0 0

1 1

2 2

4

-10 -10

-10 10

10 10

10 -10

3

100 100

1 1

2 2

Sample Output

YES

NO


题目中说明了严格定义,所以即使是点在边上也不行。

叉积,设有向量P1(x1,y1)与P2(x2,y2)

则x1*y2-x2*y1为叉积

当叉积<0 时,P1在P2的逆时针方向

当叉积>0 时,P1在P2的顺时针方向

当叉积=0 时,P1与P2的平行

总结,前对后正顺逆反。

如:x2*y1-y2*x1时>0, 则P2对于P1时顺时针的

特别:若有两点A,B,则带入计算AB和计算BA的时候求得的>0时不同的


以A为原点时,C在AB逆时针方向

以B为原点时,C在BA顺时针方向

该题中deal函数默认三个参数,其中以第一个参数为原点计算点与边的关系。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct forma
{
    double x,y;
};
double deal(forma a,forma b,forma c)
{
    return (a.x-b.x)*(a.y-c.y)-(a.y-b.y)*(a.x-c.x);
}
int main()
{
    std::ios::sync_with_stdio(false);
    int n;
    while(cin>>n)
    {
        forma stu[n];
        for(int i=0; i<n; i++)
            cin>>stu[i].x>>stu[i].y;
        int num;
        cin>>num;
        forma stu2[num];
        for(int i=0; i<num; i++)
            cin>>stu2[i].x>>stu2[i].y;
        bool judge=true;
        for(int i=0; i<num; i++)
        {
            if(deal(stu[0],stu[1],stu2[i])>=0||deal(stu[0],stu[n-1],stu2[i])<=0)///在边上也是不可以的
            {
                judge=false;
                break;
            }
            int l=1,r=n-1,mid;
            while(l<r)
            {
                mid=(l+r)>>1;
                if(deal(stu[0],stu[mid],stu2[i])>=0)///此处写不写=无所谓,因为下面可以正常判定
                    r=mid;
                else
                    l=mid+1;
            }
            if(deal(stu[r-1],stu[r],stu2[i])>=0)///在边上,则NO
            {
                judge=false;
                break;
            }
        }
        if(!judge)
            cout<<"NO"<<endl;
        else
            cout<<"YES"<<endl;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值