hrbustoj 1306:再遇攻击(计算几何,判断点是否在多边形内,水题)
再遇攻击
Time Limit: 1000 MS Memory Limit: 65536 K
Total Submit: 253(37 users) Total Accepted: 56(29 users) Rating: Special Judge: No
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
0
Sample Output
No
Author
鲁学涛
计算几何,判断点是否在多边形内。
水题,没有什么需要注意的地方。
代码:
1 #include <stdio.h>
2 struct Point{
3 double x,y;
4 };
5 struct Line{
6 Point p1,p2;
7 };
8 double xmulti(Point p1,Point p2,Point p0) //求p1p0和p2p0的叉积,如果大于0,则p1在p2的顺时针方向
9 {
10 return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
11 }
12 double Max(double a,double b)
13 {
14 return a>b?a:b;
15 }
16 double Min(double a,double b)
17 {
18 return a<b?a:b;
19 }
20 bool ponls(Point q,Line l) //判断点q是否在线段l上
21 {
22 if(q.x > Max(l.p1.x,l.p2.x) || q.x < Min(l.p1.x,l.p2.x)
23 || q.y > Max(l.p1.y,l.p2.y) || q.y < Min(l.p1.y,l.p2.y) )
24 return false;
25 if(xmulti(l.p1,l.p2,q)==0) //点q不在l的延长线或者反向延长线上,如果叉积再为0,则确定点q在线段l上
26 return true;
27 else
28 return false;
29 }
30 bool pinplg(int pointnum,Point p[],Point q)
31 {
32 Line s;
33 int c = 0;
34 for(int i=1;i<=pointnum;i++){ //多边形的每条边s
35 if(i==pointnum)
36 s.p1 = p[pointnum],s.p2 = p[1];
37 else
38 s.p1 = p[i],s.p2 = p[i+1];
39 if(ponls(q,s)) //点q在边s上
40 return true;
41 if(s.p1.y != s.p2.y){ //s不是水平的
42 Point t;
43 t.x = q.x - 1,t.y = q.y;
44 if( (s.p1.y == q.y && s.p1.x <=q.x) || (s.p2.y == q.y && s.p2.x <= q.x) ){ //s的一个端点在L上
45 int tt;
46 if(s.p1.y == q.y)
47 tt = 1;
48 else if(s.p2.y == q.y)
49 tt = 2;
50 int maxx;
51 if(s.p1.y > s.p2.y)
52 maxx = 1;
53 else
54 maxx = 2;
55 if(tt == maxx) //如果这个端点的纵坐标较大的那个端点
56 c++;
57 }
58 else if(xmulti(s.p1,t,q)*xmulti(s.p2,t,q) <= 0){ //L和边s相交
59 Point lowp,higp;
60 if(s.p1.y > s.p2.y)
61 lowp.x = s.p2.x,lowp.y = s.p2.y,higp.x = s.p1.x,higp.y = s.p1.y;
62 else
63 lowp.x = s.p1.x,lowp.y = s.p1.y,higp.x = s.p2.x,higp.y = s.p2.y;
64 if(xmulti(q,higp,lowp)>=0)
65 c++;
66 }
67 }
68 }
69 if(c%2==0)
70 return false;
71 else
72 return true;
73 }
74 int main()
75 {
76 int i,n;
77 while(scanf("%d",&n)!=EOF){
78 if(n==0) break;
79 Point t;
80 scanf("%lf%lf",&t.x,&t.y);
81 Point p[101];
82 for(i=1;i<=n;i++) //输入多边形的顶点
83 scanf("%lf%lf",&p[i].x,&p[i].y);
84 if(pinplg(n,p,t))
85 printf("Yes\n");
86 else
87 printf("No\n");
88 }
89 return 0;
90 }
Freecode : www.cnblogs.com/yym2013