ZOJ 1081 Points Within | 判断点在多边形内

题目:

给个n个点的多边形,n个点按顺序给出,给个点m,判断m在不在多边形内部



题解:

网上有两种方法,这里写一种:射线法

大体的思想是:以这个点为端点,做一条平行与x轴的射线(代码中射线指向x轴正方向)

如果交点个数为奇数的话就在内部,如果为偶数(包括0)就在外部

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 105
using namespace std;
int n,m;
struct point//点(向量的结构体)
{
    int x,y;
    point() {}//初始化
    point (int _x,int _y) :
	x(_x),y(_y) {};//用一对坐标初始化点
    inline point operator + (const point &rhs) const//向量加法
	{
	    return point(x+rhs.x,y+rhs.y);
	}
    inline point operator - (const point &rhs) const//向量减法
	{
	    return point(x-rhs.x,y-rhs.y);
	}
    inline int operator * (const point &rhs) const//向量叉乘
//向量叉乘的几何意义是以两个向量为邻边的平行四边形的有向面积 也就是|a|*|b|*sin<a,b> 这里的sin<a,b>决定了
//如果a,b是逆时针的,那么sin<a,b>大于0,有向面积大于0,反之<0
	{
	    return x*rhs.y-y*rhs.x;
	}
    friend inline int dot(const point &lhs,const point &rhs)//向量点乘
	{
	    return lhs.x*rhs.x+lhs.y*rhs.y;
	}
}q;
inline int check(const point &u,const point &v,const point &p)//判断点是不是在线段上
//u,v是线段端点,p是点
{
    int det=(u-p)*(v-p);//如果向量(u-p)*(v-p)==0就说明u,v,p共线(因为没面积)
    if (det!=0) return 0;
    int Dot=dot(u-p,v-p);//如果(u-p)点乘(v-p)<=0 就说明点在线段上
    return Dot<=0;
}
struct polygon//多边形结构体
{
    int n;
    point p[N];
    void init(int _n)
	{
	    n=_n;
	    for (int i=0;i<n;i++)
	    	scanf("%d%d",&p[i].x,&p[i].y);
	    p[n]=p[0];
	    if (Area()<0) reverse(p,p+n);//通过判断多边形的有向面积来把点规范成逆时针的
	    p[n]=p[0];
	}
    inline int Area() const
    //计算多边形的有向面积(如果点是逆时针的话就是正的,否则是负的)
	{
	    int ret=0;
	    for (int i=0;i<n;i++)
		    ret+=p[i]*p[i+1];
	    return ret=0;
	}
    bool inner (const point &q)//判断点是不是在多边形内部
	{
	    int cnt=0;
	    for (int i=0;i<n;i++)
	    {
		    if (check(p[i],p[i+1],q)) return 1;//如果点在线段上显然可以
		    int d1=p[i].y-q.y,d2=p[i+1].y-q.y;
		    int det=(p[i]-q)*(p[i+1]-q);
		    if ( (det>=0 && d1<0 && d2>=0) ||
		         (det<=0 && d1>=0 && d2<0)) ++cnt;//第一个条件是判断p在多边形内的时候,第二个是判断p在多边形外的时候
	    }
	    return cnt&1;
	}
}P;

int main()
{
    for (int tt=1;;tt++)
    {
	    scanf("%d",&n);
	    if (n==0) break;
	    scanf("%d",&m);
	    P.init(n);
	    if (tt!=1)
	        putchar(‘\n‘);
	    printf("Problem %d:\n",tt);
	    while (m--)
	    {
	        scanf("%d%d",&q.x,&q.y);
	        if (P.inner(q)) puts("Within");
	        else puts("Outside");
	    }
    }
    return 0;
}
时间: 2024-07-30 21:49:36

ZOJ 1081 Points Within | 判断点在多边形内的相关文章

zoj 1081 Points Within 判断点是否在任意多边形内(模板)

题目来源: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=81 分析: 从p点出发做平行于x轴的射线 l. 求射线与 多边形 线段的交点数num, 若是偶数 , 该点 在外, 若为奇数, 该点在内. 注意: 两个特判, 1:   一个是 射线 l 与 多边形的边  重合 , 若该p点在 线段上, 返回1, 否则 交点 记为 0 个 2: 一个是 射线与 线段的交点 ,为线段的端点, 则我们 对线段的 较低交点 不计算. 代码

ZOJ 1081 Within(点是否在多边形内)| 计算几何

ZOJ 1081 Within 我使用的是"射线法":从该点出发,作一条向左的水平射线,与多边形的边的交点有奇数个则点在多边形内. 需要注意的点: 如果点在多边形的边上特判. 考虑射线与多边形的一个交点是多边形的顶点的情况, 最左边的那个顶点算一个交点,左边第二种的那个顶点算两个交点或不算交点都行(但不能算一个交点). #include <cstdio> #include <cstring> #include <cmath> #include <

A Round Peg in a Ground Hole - POJ 1584 (判断凸多边形&amp;判断点在多边形内&amp;判断圆在多边形内)

题目大意:首先给一个圆的半径和圆心,然后给一个多边形的所有点(多边形按照顺时针或者逆时针给的),求,这个多边形是否是凸多边形,如果是凸多边形在判断这个圆是否在这个凸多边形内. 分析:判断凸多边形可以使用相邻的三个点叉积判断,因为不知道顺时针还是逆时针,所以叉积如果有有整数和负数,那么一定不是凸多边形(注意允许多多点在一条线段上).判断圆在凸多边形首先要判断圆心是否在多边形内,如果在多边形内,再次判断圆心到达到变形每条边的最短距离,如果小于半径就是不合法.ps:一道好题,通过这个题学会了不少东西.

【原创】判断点在多边形内

一.应用场景:地图应用中判断一个位置是否在一个区域内.我曾经应用在百度地图上,代码为js实现.据我了解,目前百度地图api已经提供该功能. 二.概要: 1.行政区划边界是多边形: 2.多边形分为凸多边形和凹多边形: 3.应用:产生随机数据(即一个平面坐标)在制定的行政区划边界以内(即多边形内),在正式情况下不需要从图形的层面处理数据,数据本身就有在那个区划下的属性. 三.假定: 1.多边形的点都是不重合的点: 2.给定的多边形边界坐标集就是时针顺序的,即要么符合逆时针顺序要么符合顺时针顺序,不存

Hdu 4458 Shoot the Airplane(判断点在多边形内)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4458 思路:以飞机为参考系,则飞机相对静止,子弹加上水平方向速度-v.则只需枚举时间,判断该时间时点(子弹)是否在多边形(飞机)内.注意g可以为0,分匀变速和匀速.另外本题精度要求较高,判断点在线段上用坐标差值,避免使用Dot . #include<cstdio> #include<cstring> #include<iostream> #include<algori

【转】判断点在多边形内(matlab)

inpolygon -Points inside polygonal region Syntax IN = inpolygon(X,Y,xv,yv)[IN ON] = inpolygon(X,Y,xv,yv) Description IN = inpolygon(X,Y,xv,yv) returns a matrix IN the same size as X and Y. Each element of IN is assigned the value 1 or 0 depending on

兔子-判断点在多边形内

private boolean IsPointInPolygon(List<LatLng> poly, LatLng pt) { int i, j; boolean c = false; for (i = 0, j = poly.size() - 1; i < poly.size(); j = i++) { if ((((poly.get(i).latitude <= pt.latitude) && (pt.latitude < poly .get(j).la

c# 判断点是否在区域内 点在区域内 在多边形内 判断

方法一 算法 : public int isLeft(Point P0, Point P1,Point P2)        {            int abc= ((P1.X - P0.X) * (P2.Y - P0.Y) - (P2.X - P0.X) * (P1.Y - P0.Y));            return abc;                                                               } private bool

HDU 1756 Cupid&#39;s Arrow 判断点在多边形的内部

Cupid's Arrow Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1163    Accepted Submission(s): 425 Problem Description 传说世上有一支丘比特的箭,凡是被这支箭射到的人,就会深深的爱上射箭的人.世上无数人都曾经梦想得到这支箭.Lele当然也不例外.不过他想,在得到这支箭前,