hdu_3492 Segment

//考点: 计算几何

//思路:多个线段的投影有公共点 <=> 存在这样一条直线,该直线穿过所有的线段.

思考发现,满足条件的直线可以 <=> 给定2*n个线段端点中的某两个端点所确定的直线.

换句话说,如果存在穿过所有线段的直线X,那么X"旋转"之后会被某两个线段的端点"卡住".

只要证明:任何一条跟所有线段相交的直线都可以转化成所有端点中某两个端点的情况。

于是枚举任意两个端点,然后判断直线相交。

//提交情况: 6WA 2AC

主要WA在没有考虑到非常特殊的情况:所有的线段都是同一个点 比如给了 5个线段 所有的端点都是1.0000

//经验: 如果存储的时候把起点和终点存在相邻的两格中枚举的时候就好做多了 另外issame的用法也比较巧(谢谢zhaozhouyang学长的无私帮助)

//收获: 枚举端点写的灰常的纠结啊... const doubel eps = 1e-8

//AC code

#include < stdlib.h >
#include 
< math.h >
#include
< stdio.h >
#include 
< algorithm >
using   namespace  std;
#define  maxN 300

const   double  eps  =  1e - 8 ;

/* double max(double a, double b)
{
    if(a>b) return a;
    else return b;
}

double min(double a, double b)
{
    if(a<b) return a;
    else return b;
}
*/

typedef 
struct
{
    
double  x,y;
}point;
point l[maxN
* 2 ];

double  direction(point p1,point p2, point p3)
{
// 向量p1p3和向量p2p3的叉积 p3相对p1p2的转向
     return  (p3.x - p1.x) * (p2.y - p1.y) - (p2.x - p1.x) * (p3.y - p1.y);
}
bool  online(point p1,point p2,point p3)
{
    
return  (min(p1.x,p2.x) <= p3.x && p3.x <= max(p1.x,p2.x)) && (min(p1.y,p2.y) <= p3.y && p3.y <= max(p1.y,p2.y));
}

bool  insect(point p1,point p2,point p3,point p4)
{
    
// double d1=direction(p3,p4,p1);
   
//  double d2=direction(p3,p4,p2);
     double  d3 = direction(p1,p2,p3);
    
double  d4 = direction(p1,p2,p4);
    
if (d3 * d4 < 0 )
        
return   true ;
   
//  else if(d1==0&&online(p3,p4,p1)) return true;
   
//  else if(d2==0&&online(p3,p4,p2)) return true;
     else   if (d3 == 0 return   true ;
    
else   if (d4 == 0 return   true ;
    
return   false  ;
}

int  main()
{
    
// freopen("segment.in","r",stdin);
   
//  freopen("segment.out","w",stdout);
     int  cnt  =   0 ;
    
int  N,n,i,j,k;
    
bool  flag;
    scanf(
" %d " , & N);
    
while (N -- )
    {
        cnt 
++ ;
        scanf(
" %d " , & n);
        
for (i = 0 ;i < 2 * n - 1 ;i += 2 )
        {
            scanf(
" %lf%lf%lf%lf " , & l[i].x, & l[i].y, & l[i + 1 ].x, & l[i + 1 ].y);
        }
       
/*  if (N == 39)
        {
            for(i=0;i<2*n-1;i+=2)
        {
            printf("%.0lf %.0lf,%.0lf %.0lf\n",l[i].x,l[i].y,l[i+1].x,l[i+1].y);
        }
        system("pause");

        }
*/
        
bool  issame  =   true ;
        flag 
=   false ;
        
for (i = 0 ;i <   2 * - 1   &&  flag == false ;i ++ )
            
for (j = i + 1 ;j  <   2 * &&  flag == false ;j ++ )
                {
                    
if  (fabs(l[i].x - l[j].x)  <=  eps  &&  fabs(l[i].y - l[j].y)  <=  eps)
                    
// if (l[i].x == l[j].x && l[i].y == l[j].y)
                         continue ;
                    issame 
=   false ;
                    flag
= true ;
                    
for (k = 0 ;k < 2 * n - 1 ;k += 2 )
                    {
                        
if (insect(l[i],l[j],l[k],l[k + 1 ])  ==   false )
                         {flag
= false ;
                           
break ;}
                    }

                }
        
if (flag == true   ||  issame)
            {printf(
" Yes\n " );}
        
else  printf( " No\n " );
    }
   
//  printf("%d\n",cnt);

    
return   0 ;
}

你可能感兴趣的:(hdu_3492 Segment)