凸多边形 | ||||||
| ||||||
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;
}
}