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

posted @ 2014-04-07 21:09  Freecode#  阅读(303)  评论(0编辑  收藏  举报