首页 > 代码库 > hlg1306再遇攻击--射线法判断点是否在多边形内部

hlg1306再遇攻击--射线法判断点是否在多边形内部

再遇攻击
Time Limit: 1000 MS Memory Limit: 65536 K
Total Submit: 313(40 users) Total Accepted: 91(32 users) Rating:  Special Judge: No
Description
Dota中英雄技能攻击会有一个范围,现在释放一个技能给出他的攻击范围和目标英雄的位置,问是否能攻击到。攻击范围保证是一个多边型。
Input

有多组测试数据

第一行输入1个整数n, 期中n代表攻击范围是给出的n个点组成的多边形,按照时针方向(顺或逆)依次给出,(n>=3)N = 0输入结束。

第二行a,b表示目标英雄的坐标( 0 < a,b<100)

接下来有n行,每行两个整数xy0 < x,y <100)表示每个点的坐标

攻击范围在边缘也算在内

Output

每组结果输出占一行

如果能够攻击到输出”Yes”

否则输出”No”

Sample Input

3

1 1

4 4

5 4

4 6
0

Sample Output
No
Author
鲁学涛

 

 

夜很静

静谧的有点让人享受……

其实我是在装深沉,噢哈哈哈哈哈哈

O(∩_∩)O~~

 

题目就是判断一个点是否在一个多边形内部,很简单吧==

戴某

本人却错的异常惨烈,

本人先用二分做了一下,

oj以一记wrong让我明白了一个惨痛的真理

二分只能用于判断凸四边形==

==============================

下面不扯了

介绍下今天学到的新方法

射线法

就是从查询点向任意方向引出一条射线看脚垫的个数

奇数个说明在内部‘

偶数个则在外部

很好实现吧~~

我是有多笨~~这么久简单的几行代码费了这么大劲,哎==

 

yaokaol的细节总结来就三点:
一、 对于点在某边上 则直接返回 true

二、对于平行的边则不予以考虑(这点让我理解了好久==智商捉急===)

三、对于每条边只考虑上顶点 忽略下定点(====)

 

只要注意到这三点代码就很容易实现了~~

附一下伪代码:(这位童鞋的伪代码让人眼前一亮)

上图伪代码要把判断点是否在slid上放在判断平行之前,

 

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int maxn = 55;
 8 
 9 int min(int a, int b)
10 {
11     return a > b ? b : a;
12 }
13 int max(int a, int b)
14 {
15     return a > b ? a : b;
16 }
17 
18 struct point
19 {
20     int x;
21     int y;
22 }poin[maxn];
23 
24 int cross(point p0, point p1, point p2)
25 {
26     return (p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y);
27 }
28 
29 bool check_online(point p1, point p2, point Q)
30 {
31     if(cross(p1, Q, p2) == 0 &&
32        Q.x >= min(p1.x, p2.x) && Q.x <= max(p1.x, p2.x) &&
33        Q.y >= min(p1.y, p2.y) && Q.y <= max(p1.y, p2.y) )
34         return true;
35     return false;
36 }
37 
38 bool check_two_line(point a,point b, point c, point d)
39 {
40     int h, i, j, k;
41     h = cross(a, b, c);
42     i = cross(a, b, d);
43     j = cross(c, d, a);
44     k = cross(c, d, b);
45     return h * i <= 0 && j * k <= 0;
46 }
47 
48 int main()
49 {
50     int n;
51     while(scanf("%d",&n) && n)
52     {
53         point Q, P, p1, p2;
54         scanf("%d %d",&Q.x, &Q.y);
55         P.x = 101, P.y = Q.y;
56         for(int i = 0; i < n; i++)
57             scanf("%d %d",&poin[i].x, &poin[i].y);
58         bool flag = false;
59         int cnt = 0;
60         for(int i = 0; i < n; i++)
61         {
62             p1 = poin[i], p2 = poin[(i+1)%n];
63             if(check_online(p1, p2, Q))
64             {
65                 flag = true;
66                 break;
67             }
68             if(p1.y == p2.y)
69                 continue;
70             if(Q.y > min(p1.y, p2.y) && Q.y <= max(p1.y, p2.y))
71             {
72                 if(check_two_line(Q, P, p1, p2))
73                     cnt++;
74             }
75         }
76         //printf("%d\n",cnt);
77         if(flag)
78         {
79             printf("Yes\n");
80             continue;
81         }
82         if(cnt % 2 == 1)
83             printf("Yes\n");
84         else
85             printf("No\n");
86     }
87     return 0;
88 }
View Code