HDU 1756 Cupid's Arrow (几何问题,判定点在多边形内部)

题意:中文的么,自己看喽。

析:很容易明白是判定点是不是在多边形内部,一般是向量来判定,我一开始用点在向量的右侧,因为是顺时针给的,只要点全在外侧或边上,

就可以,暴力一下就ok。由于这个是浮点数,一定要注意精度,也就是误差,结果WA了好几次,一气之下,我改了算法,采用转角法,

假想有一条向右的射线,统计多边形穿过这条射线正反多少次,顺时针减1,逆时针加1。一定要注意这个精度控制,不然就WA。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;
const double eps = 1E-10;
const int maxn = 100 + 10;
struct node{
    double x, y;
    node() { }
    node(double xx, double yy) : x(xx), y(yy) { }
};
node operator + (node A, node B) {  return node(A.x+B.x, A.y+B.y); }
node operator - (node A, node B) {  return node(A.x-B.x, A.y-B.y); }
int n;
node a[maxn];

int dcmp(double x){
    if(fabs(x) < eps)  return 0;
    else  return x < 0 ? -1 : 1;
}

double cross(node A, node B){  return A.x * B.y - A.y * B.x; }

bool solve(node p){
    int wn = 0;
    for(int i = 0; i < n; ++i){
        int k = dcmp(cross(a[(i+1)%n]-a[i], p-a[i]));
        int d1 = dcmp(a[i].y-p.y);
        int d2 = dcmp(a[(i+1)%n].y-p.y);
        if(k > 0 && d1 <= 0 && d2 > 0)  ++wn;
        if(k < 0 && d2 <= 0 && d1 > 0)  --wn;
    }
    if(wn != 0)  return true;
    return false;
}

int main(){
    int m;
    while(~scanf("%d", &n)){
        for(int i = 0; i < n; ++i)  scanf("%lf %lf", &a[i].x, &a[i].y);
        scanf("%d", &m);
        while(m--){
            double x, y;
            scanf("%lf %lf", &x, &y);
            if(solve(node(x, y)))  puts("Yes");
            else  puts("No");
        }
    }
    return 0;
}

HDU 1756 Cupid's Arrow (几何问题,判定点在多边形内部)

时间: 2024-11-16 16:24:17

HDU 1756 Cupid's Arrow (几何问题,判定点在多边形内部)的相关文章

HDU 1756 Cupid&#39;s Arrow(点在多边形内判定)

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

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当然也不例外.不过他想,在得到这支箭前,

【HDOJ】1756 Cupid&#39;s Arrow

图论,点在多边形内部的判定. 1 /* 1756 */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #include <vector> 9 #include <deque> 10 #include <algorithm&

HDU 2444 The Accomodation of Students 二分图判定+最大匹配

题目来源:HDU 2444 The Accomodation of Students 题意:n个人是否可以分成2组 每组的人不能相互认识 就是二分图判定 可以分成2组 每组选一个2个人认识可以去一个双人间 最多可以有几组 思路:二分图判定+最大匹配 #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn = 550; int vis[maxn];

HDU 2444 The Accomodation of Students二分图判定和匈牙利算法

本题就是先判断是否可以组成二分图,然后用匈牙利算法求出最大匹配. 到底如何学习一种新算法呢? 我也不知道什么方法是最佳的了,因为看书本和大牛们写的匈牙利算法详细分析,看了差不多两个小时没看懂,最后自己直接看代码,居然不到半个小时看懂了.然后就可以直接拿来解题啦. 比如topcoder上有这个算法的很详细的分析,真没看懂. 代码居然比分析更清晰了?我也不好下结论. 但是我觉得主要的思想还是有作用的. 说说我对这个算法的理解吧: 1 假设二分图分为两个集合 U, V,那么从一个集合U出发 2 U的一

hdu 1756(判断点是否在多边形中)

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

hdu 5285 wyh2000 and pupil(二分图判定)

对每两个不认识的人连一条边,则此题可转化为二分图判定(二分图可有多个). 如果有一部分图判定为不是二分图,则输出“Poor wyh”. 否则,分别累加每个二分图的最多的颜色数. #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <string> #include <stack> #include <cmat

HDU 1432 Lining Up(几何)

http://acm.hdu.edu.cn/showproblem.php?pid=1432 题目大意: 2维平面上给定n个点,求一条直线能够穿过点数最多是多少. 解题思路: 因为题目给定的n(1~700),所以枚举,时间复杂度是O(n^3),不会超时. 枚举两个点,然后判断剩下的点是否在这条直线. AC代码: 1 #include<cstdio> 2 3 struct Point{ 4 int x, y; 5 6 Point(int x = 0, int y = 0): x(x), y(y)

HDU 1665 - Different Digits(几何 + 欧拉定理)

题意:在一个平面上,给定一个由 n 个点(4 <= n <= 300)组成的一封闭笔画图形(第一个端点与第 n 个端点重合),求这个图形将平面分成几个部分. 需要用到欧拉定理: 欧拉定理:设图的顶点数为 v ,边数(三维中为棱的个数)为 e ,面数为 f ,则v + f - e = 2. 则若求面数,只要求出顶点数 v 和边数 e,即能得出答案 f = e + 2 - v. (注意:这里的边数 e,是指的单独一条线段,若中间被点分隔开,则算作多条线段而非一条) 具体处理如下: 1.先枚举任意两