[编程题]凸多边形内点统计

链接: https://blog.csdn.net/acm_cxq/article/details/51285463

1原题

二维平面上给定一个凸多边形和若干点,小强想要查询有多少个点在凸多边形内部,在边上的点不算作内部)。
凸多边形由顺序的顶点序列构成,顶点以及要查询的点都在整数坐标上。
如由(1,0), (0,1), (-1,0), (0,-1)构成的四边形中,(0,0)点在内部,而(1,1)点在外部。

输入描述:
首先输入vn(n<=1e4),表示凸多边形的顶点个数;
接下来输入vn个顶点,每个顶点由两个整数构成,分别表示横纵坐标x、y(-1e4<=x,y<=1e4);
然后输入pn(pn<=1e4),表示要查询数;
接下来输入pn个点,每个点由两个整数构成,分别表示横纵坐标x、y(-1e4<=x,y<=1e4)

输出描述:
输出一个整数,表示在凸多边形内部的点数

示例1

输入
4 1 0 0 1 -1 0 0 -1
2 0 0 1 1

2思路

这里也是将别人的思路进行重新整理:
在这里插入图片描述
1,在凸多边形的条件下,判断点p是否位于该多边形中:

  1. logN射线法
    默认凸多边形的顶点是顺时针顺序排列,从在图例中给出的角度关系,可以看出必定的条件:点p在线段01的左边,点p在线段06的右边;满足这个关系之后,采用4和0的二分,判断点p位于线段02的左边还是右边,如果是在左边,我们在4和2之间二分,判断线段03与点p之间的关系,得到的如果是点p在03的右边,此时我们发现2与3刚好相邻,此时认为点p在02和03之间,此时需要判断点p是否在线段23的内侧,也就是左边。

以上是基于5个点的简单判断,如果尝试其他更多点,也都满足这种思路。如果考虑点的逆时针,上面的相对关系都是反过来的。

接下来有一个数学知识,判断点在线段的左侧还是右侧,当然,这是在二维的情况下,就要用到叉积的概念;
链接: 忘记了的话点这里.
我们通过上图可以知道,向量01 叉乘 向量0p,得到的向量指向屏幕向内,向量0p 叉乘 向量01 ,得到的向量指向屏幕向外;向内为负数,向外为正数。
设A(x1,y1),B(x2,y2),给定点是C(x3,y3),构造两条矢量边:
AB=(x2-x1,y2-y1), AC=(x3-x1,y3-y1)
则AB和AC的叉积为(2*2的行列式):
|x2-x1, y2-y1|
|x3-x1, y3-y1|
值为:r = (x2-x1)(y3-y1) - (y2-y1)(x3-x1)
然后利用右手法则进行判断:
如果r > 0,则点C在矢量AB的左边
如果r < 0,则点C在矢量AB的右边

double cross(cpoint p0, cpoint p1, cpoint p2)
{
     return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}
bool Compl_inside_convex(const cpoint & p,cpoint *con,int n)
{
     if(n<3) return false;
     if(cross(con[0],p,con[1])>-eps) return false;
     if(cross(con[0],p,con[n-1])<eps) return false;
     
     int i=2,j=n-1;
     int line=-1;
     while(i<=j)
     {
        int mid=(i+j)>>1;
        if(cross(con[0],p,con[mid])>-eps)
        {
            line=mid;
            j=mid-1;
        }
        else i=mid+1;
     }
     return cross(con[line-1],p,con[line])<-eps;
}

吐槽一下,在编辑文章的时候,为什么大段复制的时候会出现界面卡死的情况,复制最好一行一行的进行

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值