题意:
给你n条线段,问你有没有可能存在一条直线可以让所有线段在这条直线上的投影交于一点。
题解:
题意可以转化成所有是否存在一直线与所有线段有交点,而要求的直线就是该直线的一条垂线。垂足即是所有线段投影的焦点,
那么枚举所有线段的端点,来枚举这条直线,因为如果一条直线能能和所有n条线段相交,那么他一定能过两条线段的端点,
其实可以这样枚举,枚举一个线段的端点,另外一点在另外一条线段从一端点到另外一端点枚举,这样枚举两个线段就行了,但是这样复杂度更高,,
接下来就是判断线段与直线能否相交,注意还要去重,两个点如果重复会错。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
#define x first
#define y second
const double eps=1e-8;
const double PI=acos(-1.0);
const int maxn=105;
int sgn(double x){
if(fabs(x)<eps) return 0;
if(x<0) return -1;
return 1;
}
struct Point{
double x,y;
Point(){}
Point(double _x,double _y){
x=_x;y=_y;
}
Point operator -(const Point &b)const{
return Point(x-b.x,y-b.y);
}
double operator ^ (const Point &b)const{
return x*b.y - y*b.x;
}
};
struct Line{
Point s,e;
Line(){}
Line(Point _s,Point _e){
s=_s;e=_e;
}
};
bool Seg_inter_line(Line l1,Line l2){
return sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e))<=0;
}
Point p[maxn*2];
Line l[maxn],tl;
int main(){
int t,n,cnt;
double x1,x2,y1,y2;
scanf("%d",&t);
while(t--){
cnt=0;
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
p[++cnt]={x1,y1};
p[++cnt]={x2,y2};
l[i]={p[cnt-1],p[cnt]};
}
int f=1;
for(int i=1;i<cnt;++i){
for(int j=i+1;j<=cnt;++j){
tl={p[i],p[j]};
f=1;
for(int k=1;k<=n;++k){
if (fabs(p[i].x-p[j].x) < eps && fabs(p[i].y-p[j].y) < eps) {
f=0; break;
}
if(Seg_inter_line(tl,l[k])==0) {
f=0;break;
}
}
if(f) {break;}
}if(f) {break;}
}
if(f||n<3) puts("Yes!");
else puts("No!");
}
return 0;
}