zoukankan      html  css  js  c++  java
  • HDU 1086 You can Solve a Geometry Problem too

    题目:http://www.cnblogs.com/lujiacheng/admin/EditPosts.aspx?opt=1

    给了n条线段,求有几个交点,重复的也要算。

    判断两线段是否相交:

      我们分两步确定两条线段是否相交:

      (1)快速排斥试验

        设以线段 P1P2 为对角线的矩形为R, 设以线段 Q1Q2 为对角线的矩形为T,如果R和T不相交,显然两线段不会相交。

      (2)跨立试验

        如果两线段相交,则两线段必然相互跨立对方。若P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ) 和( P2 - Q1 )位于矢量( Q2 - Q1 ) 的两侧,即( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0。上式可改写成( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0。当 ( P1 - Q1 ) × ( Q2 - Q1 ) = 0 时,说明 ( P1 - Q1 ) 和 ( Q2 - Q1 )共线,但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2上。所以判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。同理判断Q1Q2跨立P1P2的依据是:( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) >= 0。具体情况如下图所示:

        

      在相同的原理下,对此算法的具体的实现细节可能会与此有所不同,除了这种过程外,大家也可以参考《算法导论》上的实现。

    关于计算几何算法概述网站 http://dev.gameres.com/Program/Abstract/Geometry.htm 一个挺好的网站

    向量的运算:

    向量:u=(u1,u2,u3) v=(v1,v2,v3)

    叉积公式:u x v = (u2v3-v2u3 , u3v1-v3u1 , u1v2-u2v1 )

    点积公式:u * v = u1v1+u2v2+u3v3

    以上是三维的,二维的是u = (u1,u2)    v=(v1,v2)

    叉积公式:u x v = u1v2 - u2v1

    点积公式: u * v = u1v1+u2v2

    代码:

    View Code
     1 #include<stdio.h>
    2
    3 struct node
    4 {
    5 double x,y;
    6 }start[101],end[101];
    7
    8 double direction(node p1,node p2,node p)
    9 {
    10 return (p1.x-p.x)*(p2.y-p.y)-(p1.y-p.y)*(p2.x-p.x);
    11 }
    12
    13 bool is_on_segment(node p1,node p2,node p)
    14 {
    15 double min,max;
    16 if(p1.x<p2.x)
    17 {
    18 min=p1.x;
    19 max=p2.x;
    20 }
    21 else
    22 {
    23 min=p2.x;
    24 max=p1.x;
    25 }
    26 if(p.x>=min&&p.x<=max)
    27 return 1;
    28 return 0;
    29 }
    30
    31 bool intersect_segment(node p1,node p2,node p3,node p4)
    32 {
    33 double d1=direction(p1,p2,p3);
    34 double d2=direction(p1,p2,p4);
    35 double d3=direction(p3,p4,p1);
    36 double d4=direction(p3,p4,p2);
    37 if(d1*d2<0&&d3*d4<0)
    38 return 1;
    39 if(d1==0&&is_on_segment(p1,p2,p3))//去掉on_segment可以判断线段是否与直线相交
    40 return 1;
    41 if(d2==0&&is_on_segment(p1,p2,p4))
    42 return 1;
    43 if(d3==0&&is_on_segment(p3,p4,p1))
    44 return 1;
    45 if(d4==0&&is_on_segment(p3,p4,p2))
    46 return 1;
    47 return 0;
    48 }
    49
    50 int main()
    51 {
    52 int i,j,num,n;
    53 while(scanf("%d",&n)!=EOF&&n)
    54 {
    55 for(i=0;i<n;i++)
    56 {
    57 scanf("%lf%lf%lf%lf",&start[i].x,&start[i].y,&end[i].x,&end[i].y);
    58 }
    59 num=0;
    60 for(i=0;i<n;i++)
    61 {
    62 for(j=i+1;j<n;j++)
    63 {
    64 if(intersect_segment(start[i],end[i],start[j],end[j]))
    65 {
    66 num++;
    67 }
    68 }
    69 }
    70 printf("%d\n",num);
    71 }
    72 return 0;
    73 }

      

  • 相关阅读:
    template(2.2)
    Filter过滤链条
    The 3n + 1 problem
    Struts2.3+Spring4.0
    康托展开
    templates(2.1)
    templates(1.2)
    templates(1.1)
    我和你
    Android 的上下文菜单: Context Menu
  • 原文地址:https://www.cnblogs.com/lujiacheng/p/2119636.html
Copyright © 2011-2022 走看看