JAVA射线_射线法 - 萌德真帅 - 博客园

射线法

这是一个大佬看了都说简单的算法。。。。(甚至觉得没有掌握的必要)

QAQ

这个算法是用来判断一个点是否在一个多边形以内。很简单 将这个点沿着x轴的正方向作射线。如果穿过的边数为基数,那么这个点在多边形内;反之不在。

由于有可能出现经过两条边的相邻的点,而被重复计算的情况。我们只需要采用上加下不加策略,即如果射线经过了这条边的上顶点,则cnt++,如果经过下顶点,则不变。经过这条边上除了上顶点和下顶点的地方,cnt++。正确性显然。

另外因为我们需要将每条边都遍历完。而我们只向 x的正方向做了射线,那么完全在询问点的左边的边不能计算。可是每条边都遍历,难道不会计算吗?

不!不会计算。自己去手动模拟一下条件,当其在左边的时候,康康是否被重复计算了呢(没有)

#include

#include

#include

#include

#include

using namespace std;

const int maxn=1e6;

int n,m;

struct point{

double x,y;

point(){x=0,y=0;}

point(double a,double b){x=a,y=b;}

point operator+(const point &b)const{return point(x+b.x,y+b.y);}

point operator-(const point &b)const{return point(x-b.x,y-b.y);}

point operator*(const double &b)const{return point(x*b,y*b);}

double operator*(const point &b)const{return x*b.y-y*b.x;}

double dot()const{return x*x+y*y;}

double dot(const point &b)const{return x*b.x+y*b.y;}

};

point p[maxn];

inline double cross(const point &a,const point &b){return a.x*b.y-a.y*b.x;}

inline double d(const point &a,const point &b){return sqrt((a-b).dot());}

inline bool check(const point &a,const point &b,const point &c){

if(fabs(d(a,c)+d(b,c)-d(a,b))==0) return true;

return false;

}

inline double area(){

double sum=0;

for(int i=0;i

return sum;

}

void init(){

for(int i=0;i

scanf("%lf %lf",&p[i].x,&p[i].y);

}

p[n]=p[0];

//if(area()<0) reverse(p,p+n);

p[n]=p[0];

}

int main(){

for(int test=1;;test++){

scanf("%d",&n);if(n==0) break;

//scanf("%d",&m);

init();

//if(test!=1) printf("\n");

//printf("Problem %d:\n",test);

//while(m--){

int cnt=0;

point q;

scanf("%lf %lf",&q.x,&q.y);

for(int i=1;i<=n;i++){

if(check(p[i-1],p[i],q)){printf("T\n");break;}

double height1=p[i-1].y-q.y,height2=p[i].y-q.y;

double cro=cross((p[i-1]-q),(p[i]-q));

if((cro>=0 && height1<0 && height2>=0) || (cro<=0 && height1>=0 && height2<0)) cnt++;

}

if(cnt&1) printf("T\n");

else printf("F\n");

//}

}

return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值