hdu 1756 Cupid's Arrow (计算几何,点是是否完全在多边形内)

版权声明:本文为博主原创文章,转载请标明原博客。 https://blog.csdn.net/sdau_fangshifeng/article/details/86520005

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1756

Cupid's Arrow

Problem Description

传说世上有一支丘比特的箭,凡是被这支箭射到的人,就会深深的爱上射箭的人。
世上无数人都曾经梦想得到这支箭。Lele当然也不例外。不过他想,在得到这支箭前,他总得先学会射箭。
日子一天天地过,Lele的箭术也越来越强,渐渐得,他不再满足于去射那圆形的靶子,他开始设计各种各样多边形的靶子。
不过,这样又出现了新的问题,由于长时间地练习射箭,Lele的视力已经高度近视,他现在甚至无法判断他的箭射到了靶子没有。所以他现在只能求助于聪明的Acmers,你能帮帮他嘛?

Input

本题目包含多组测试,请处理到文件结束。
在每组测试的第一行,包含一个正整数N(2<N<100),表示靶子的顶点数。
接着N行按顺时针方向给出这N个顶点的x和y坐标(0<x,y<1000)。
然后有一个正整数M,表示Lele射的箭的数目。
接下来M行分别给出Lele射的这些箭的X,Y坐标(0<X,Y<1000)。

Output

对于每枝箭,如果Lele射中了靶子,就在一行里面输出"Yes",否则输出"No"。

Sample Input

4

10 10

20 10

20 5

10 5

2

15 8

25 8

Sample Output

Yes 
No

计算集合的模板题目,注意的要是在边缘上不算(即在线段上不算)

This is the code

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define EPS 1e-8
#define MOD 1e9+7
#define LL long long
#define ULL unsigned long long     //1844674407370955161
#define INT_INF 0x7f7f7f7f      //2139062143
#define LL_INF 0x7f7f7f7f7f7f7f7f //9187201950435737471
//const int dr[]= {0, 0, -1, 1, -1, -1, 1, 1};
//const int dc[]= {-1, 1, 0, 0, -1, 1, -1, 1};
struct point
{
    double x;
    double y;
} p,d[105];
int n;

bool on_line(point a, point b, point c)//判断点在线段上
{
    if (c.x>=min(a.x,b.x) && c.x<=max(a.x,b.x) && c.y>=min(a.y, b.y) && c.y<=max(a.y,b.y))//去掉在线段上的麻烦
    {
        return (abs((c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y))<= EPS);
    }
    return false;
}

bool on_flat()
{
    int cnt=0;
    scanf("%lf %lf",&p.x,&p.y);
    point p1=d[0];
    point p2;
    for(int i=1; i<=n; ++i)
    {
        p2=d[i%n];
        if(on_line(p1,p2,p))//表示在线段上
        {
            cnt=0;
            break;
        }
        if(p.y>min(p1.y,p2.y))//如果射线交于边的下端点,不算相交,所以是>
        {
            if(p.y<=max(p1.y,p2.y))
            {
                if(p.x<=max(p1.x,p2.x))
                {
                    if(p1.y!=p2.y)//如果射线和边重合,不算
                    {
                        //判断是否满足在这个边的左边,其中(p1.x - p2.x) / (p1.y - p2.y)为tan
                        double tem=(p.y-p2.y)*(p1.x-p2.x)/(p1.y-p2.y)+p2.x;
                        if( p1.x==p2.x || p.x<=tem)
                            cnt++;
                    }
                }
            }
        }
        p1=p2;
    }
    if(cnt&1)
        puts("Yes");
    else
        puts("No");
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=0; i<n; ++i)
            scanf("%lf %lf",&d[i].x,&d[i].y);
        int m;
        scanf("%d",&m);
        while(m--)
            on_flat();
    }
    return 0;
}

 

猜你喜欢

转载自blog.csdn.net/sdau_fangshifeng/article/details/86520005