//考点: 计算几何
//思路:多个线段的投影有公共点 <=> 存在这样一条直线,该直线穿过所有的线段.
思考发现,满足条件的直线可以 <=> 给定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 * n - 1 && flag == false ;i ++ )
for (j = i + 1 ;j < 2 * n && 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 ;
}
#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 * n - 1 && flag == false ;i ++ )
for (j = i + 1 ;j < 2 * n && 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 ;
}