题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1756
分析:[射线法]
从已知点向x+oo远处向一水平射线,判断射线与多边形的交点个数,
若为偶数,则点在多边形外,反之则在多边形内。
注意几种特殊情况:
1、边和射线共线;
2、边的端点在射线上(上、下两端点只能考虑一个)
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<iomanip>
using namespace std;
const int maxn=100000;
const int inf = 0xFFFFFFF;
int n;
struct point{
double x,y;
void read(){
scanf("%lf%lf",&x,&y);
}
}f[maxn];
struct segment {
point a;
point b;
}seg;
double cross(point A,point B,point C){///叉积
return (B.x-A.x)*(C.y-A.y)-(C.x-A.x)*(B.y-A.y);
}
bool Dot_Segment(point D,segment R){ ///点在线段上
if(D.x<min(R.a.x,R.b.x)||D.x>max(R.a.x,R.b.x)||
D.y<min(R.a.y,R.b.y)||D.y>max(R.a.y,R.b.y))
return false;
if(cross(R.a,R.b,D))
return false;
return true;
}
bool Segmentcrossing(segment R,segment T){///线段相交
return (cross(R.a,R.b,T.a)*cross(R.a,R.b,T.b)<0&&
cross(T.a,T.b,R.a)*cross(T.a,T.b,R.b)<0);
}
bool work(point D){
point M;
M.x=inf;
M.y=D.y;
seg.a=D;
seg.b=M;
int num=0;
for(int i=1;i<=n;++i){
segment R;
R.a=f[i]; R.b=f[i+1];
if(Dot_Segment(D,R))///点在边上
return true;
if(cross(R.a,R.b,D)==0)///边和射线平行,即边水平
continue;
if(Dot_Segment(R.a,seg)){///边的上端点在射线上
if(R.a.y>R.b.y) num++;
}
else if(Dot_Segment(R.b,seg)){
if(R.a.y<R.b.y) num++;
}
else if(Segmentcrossing(R,seg))///射线和边相交
num++;
}
return num%2;
}
int main(){
while(~scanf("%d",&n)){
for(int i=1;i<=n;++i)
f[i].read();
f[n+1]=f[1];
int m;
scanf("%d",&m);
while(m--){
point D; D.read();
if(work(D)) puts("Yes");
else puts("No");
}
}
return 0;
}
该博客介绍了如何使用射线法判断一个点是否位于多边形内部,通过分析射线与多边形边界交点的奇偶性。文章特别提到了处理特殊情况,如边与射线共线以及边端点在射线上的情况。

502

被折叠的 条评论
为什么被折叠?



