zoj1081 Points Within

  1. //zoj1081 Points Within
  2. //Accepted 1081 C ++ 00:00.00 396K
  3. //(?)处有问题,不过还是AC
  4. #include <stdio.h>
  5. #define MAXN 100
  6. #define INF 1e10
  7. struct point { double x,y;};
  8. int n;
  9. double xmult(double x1,double y1,double x2,double y2){return x1*y2-x2*y1;}
  10. double xmult3(point p1,point p2,point p0)
  11. {return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}
  12. //判点p1p2在线段p3p4同侧(不包括在直线线上)
  13. bool same_side(point p1,point p2,point p3,point p4)
  14. {
  15.        double dx,dy,dx1,dy1,dx2,dy2;
  16.        dx = p4.x-p3.x, dy = p4.y-p3.y;
  17.        dx1 = p1.x-p3.x, dy1 = p1.y-p3.y;
  18.        dx2 = p2.x-p4.x, dy2 = p2.y-p4.y;
  19.        return xmult(dx,dy,dx1,dy1)*xmult(dx,dy,dx2,dy2)>0.0;
  20. }
  21. //p1p2p3p4相交(包括端点)
  22. bool intersect(point p1,point p2,point p3,point p4)
  23. {
  24.        return (!same_side(p1,p2,p3,p4) && !same_side(p3,p4,p1,p2));
  25. }
  26. //判点q在线段p1p2(包括端点)
  27. bool dot_online(point q,point p1,point p2)
  28. {
  29.        return xmult3(q,p1,p2)==0.0 &&
  30.               (q.x-p1.x)*(q.x-p2.x)<=0.0 &&
  31.               (q.y-p1.y)*(q.y-p2.y)<=0.0;
  32. }
  33. //判点q在多边形P(p[0,1,...,n-1]P的邻接顶点)(包括在边上),射线穿刺、奇偶校验法
  34. /* Special case
  35.   y|       __
  36.    |      /  /
  37.    |     / .__/____//______qs
  38.    |    /   q        /
  39. ___|____/____________/____x
  40.    |     /__________/
  41. (a) q->qs overlap the edge of P
  42.  
  43.   y|       __
  44.    |      /  /
  45.    |     /    /_.__//
  46.    |    /        q   /
  47. ___|____/____________/____x
  48.    |     /__________/
  49. (b) q is on the edge of P (true)
  50.  
  51.   y|       __
  52.    |      /._/_____________qs
  53.    |     /  q /____//
  54.    |    /            /
  55. ___|____/____________/____x
  56.    |     /__________/
  57. (c) q->qs cross the vertex of P
  58.  
  59.   y|       __
  60.    |      /  /
  61.    |     /    /____//
  62.    |    /  q.________/______qs
  63. ___|____/____________/____x
  64.    |     /__________/
  65. (d) q-qs cross the vertex of P
  66.  
  67. Sample Input
  68. 9 5
  69.  
  70. 1 1
  71. 4 1
  72. 6 3
  73. 5 5
  74. 4 4
  75. 2 4
  76. 1 6
  77. -1 6
  78. -3 3
  79.  
  80. 1 4(a)
  81. 3 4(b)
  82. 1 5(c)
  83. 1 3(d)
  84. -5 3(d)
  85. 0
  86. Sample Output
  87. Within
  88. Within
  89. Within
  90. Within
  91. Outside
  92. */
  93. bool inside_polygon(point q,point *p,int n)
  94. {
  95.        point qs=q;
  96.        qs.x = INF;//construct radial q->qs
  97.        int cnt = 0;
  98.        for (int i=0; i<n; ++i){
  99.               int j=(i+1)%n,k=(i+2)%n;
  100.               if (dot_online(q,p[i],p[j])) return true;//case (b)
  101.               if (intersect(q,qs,p[j],p[k])) cnt++;//case (c) and common
  102. //(?) if (dot_online(p[j],q,qs) && !same_side(p[i],p[k],q,qs)) cnt--;//case (d)
  103. //(?) if (dot_online(p[j],q,qs) && dot_online(p[k],q,qs)) cnt--;//case (a)
  104.        }
  105.        printf ("%d",cnt);
  106.        return cnt%2!=0;
  107. }
  108. void solve()
  109. {
  110.        int m;
  111.        point q,p[MAXN];
  112.        scanf ("%d",&m);
  113.        for (int i=0; i<n; ++i) scanf ("%lf %lf",&p[i].x,&p[i].y);
  114.        while (m--){
  115.               scanf ("%lf %lf",&q.x,&q.y);
  116.               if (inside_polygon(q,p,n))
  117.                      printf ("Within/n");
  118.               else printf ("Outside/n");
  119.        }
  120. }
  121. int main()
  122. {
  123. #ifdef ONLINE_JUDGE
  124. #else
  125.        freopen("1081.txt","r",stdin);
  126. #endif
  127.        int t=0;
  128.        while (scanf("%d",&n)!=EOF && n){
  129.               if (t) printf ("/n");
  130.               printf ("Problem %d:/n",++t);
  131.               solve();
  132.        }
  133. #ifdef ONLINE_JUDGE
  134. #else
  135.        fclose(stdin);
  136. #endif
  137.        return 0;
  138. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值