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

你可能感兴趣的:(水题)