zoj1081

来源:互联网 发布:手机如何复制淘宝商品 编辑:程序博客网 时间:2024/06/02 05:30
#include <iostream>#include <queue>   #include <stack>   #include <math.h>   #include <stdio.h>   #include <stdlib.h>      #include <limits.h>   #include <string.h>   #include <algorithm> using namespace std;  const int MAX = 110;  const double eps = 1e-6;  struct point{      double x,y;  };  struct beeline{      point a,b;  };  point p[MAX];  int n;  bool dy(double x,double y)  // x > y    {      return x > y + eps;  }  bool xy(double x,double y) // x < y    {      return x < y - eps;  }  bool dyd(double x,double y) // x >= y    {      return x > y - eps;  }  bool xyd(double x,double y) // x <= y    {      return x < y + eps;  }  bool dd(double x,double y)  // x == y    {      return fabs( x - y ) < eps;  }  double crossProduct(point a,point b,point c)//向量 ac 在 ab 的方向    {      return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);  }  bool onSegment(point a, point b, point c)  {      double maxx = max(a.x,b.x);      double maxy = max(a.y,b.y);      double minx = min(a.x,b.x);      double miny = min(a.y,b.y);      if( dd(crossProduct(a,b,c),0.0) && dyd(c.x,minx) && xyd(c.x,maxx) && dyd(c.y,miny) && xyd(c.y,maxy) )          return true;      return false;  }  bool segIntersect(point p1,point p2, point p3, point p4)  {      double d1 = crossProduct(p3,p4,p1);      double d2 = crossProduct(p3,p4,p2);      double d3 = crossProduct(p1,p2,p3);      double d4 = crossProduct(p1,p2,p4);      if( xy(d1 * d2,0.0) && xy( d3*d4,0.0 ) )         return true;      if( dd(d1,0.0) && onSegment(p3,p4,p1) )          return true;      if( dd(d2,0.0) && onSegment(p3,p4,p2) )          return true;      if( dd(d3,0.0) && onSegment(p1,p2,p3) )          return true;      if( dd(d4,0.0) && onSegment(p1,p2,p4) )          return true;      return false;  }  bool inPolygon(point pot)  {      int count = 0;      beeline l;      l.a = pot;      l.b.x = 1e10;      l.b.y = pot.y;      p[n] = p[0];      for(int i=0; i<n; i++)      {          if( onSegment(p[i],p[i+1],pot) )              return true;          if( !dd(p[i].y,p[i+1].y) )          {              int tmp = -1;              if( onSegment(l.a,l.b,p[i]) )                  tmp = i;              else                  if( onSegment(l.a,l.b,p[i+1]) )                      tmp = i+1;              if( tmp != -1 && dd(p[tmp].y,max(p[i].y,p[i+1].y)) )                  count++;              else                  if( tmp == -1 && segIntersect(p[i],p[i+1],l.a,l.b) )                      count++;          }     }      if( count % 2 == 1 )          return true;      return false;  }  int main()  {      int m;      int ind = 1;      point pot;      while( scanf("%d",&n) && n )      {          if( ind != 1 )              printf("\n");          scanf("%d",&m);          for(int i=0; i<n; i++)              scanf("%lf %lf",&p[i].x,&p[i].y);          printf("Problem %d:\n",ind++);         while( m-- )          {             scanf("%lf %lf",&pot.x,&pot.y);             if( inPolygon(pot) )                  printf("Within\n");              else                 printf("Outside\n");          }      }  return 0;  }  


题目说的是菜鸟题,可对于我这种没有经过专业相关数学训练的人来说,着实不简单。

主要就是以待测点为顶点做射线,平常来说,如果和边有偶数个交点,则在外面,因为穿进去又穿出来。如果有

奇数个交点,则在里面。

特殊情况:1,一条边在射线上,相当于没有穿,所以0个顶点。2,一个点在边上,由于其连接着两条边,所以相当于穿一次。如果相关的两条边都在射线一侧,则为偶数,否则为奇数。

 

原创粉丝点击