hlg1306再遇攻击--射线法判断点是否在多边形内部
再遇攻击 | ||||||
|
||||||
Description | ||||||
Dota中英雄技能攻击会有一个范围,现在释放一个技能给出他的攻击范围和目标英雄的位置,问是否能攻击到。攻击范围保证是一个多边型。 | ||||||
Input | ||||||
有多组测试数据 第一行输入1个整数n, 期中n代表攻击范围是给出的n个点组成的多边形,按照时针方向(顺或逆)依次给出,(n>=3)N = 0输入结束。 第二行a,b表示目标英雄的坐标( 0 < a,b<100) 接下来有n行,每行两个整数x,y(0 < x,y <100)表示每个点的坐标 攻击范围在边缘也算在内 |
||||||
Output | ||||||
每组结果输出占一行 如果能够攻击到输出”Yes” 否则输出”No” |
||||||
Sample Input | ||||||
3 1 1 4 4 5 4 4 6 |
||||||
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 }