ACWING2984. 线段
ACWING2984. 线段
描述
在二维平面内有 n 条线段,请你编写一个程序,判断是否存在一条直线满足将这 n 条线段投影到该直线上后,所有的投影线段至少具有一个公共点。
思路
转化为存在一条直线经过所有线段,再转化为存在一条经过两个点的直线经过所有线段。
代码
#include <bits/stdc++.h>
using namespace std;
const double EPS=1e-8;
#define x first
#define y second
typedef pair<double,double> pdd;
const int N=210;
int n;
pdd q[N],a[N],b[N];
int cmp(double x,double y){
if(fabs(x-y) < EPS) return 0;
if(x<y) return -1;
return 1;
}
int sign(double x){
if(fabs(x)<EPS) return 0;
if(x<0) return -1;
return 1;
}
double cross(double x1,double y1,double x2,double y2){
return x1*y2-x2*y1;
}
double area(pdd a,pdd b,pdd c){
return cross(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
bool check(){
for(int i=0;i<n*2;i++){
for(int j=i+1;j<n*2;j++)
{
if(!cmp(q[i].x,q[j].x) && !cmp(q[i].y,q[j].y)) continue;
bool flag=true;
for(int k=0;k<n;k++){
if(sign(area(q[i],q[j],a[k])*area(q[i],q[j],b[k]))>0){
flag=false;
break;
}
}
if(flag) return true;
}
}
return false;
}
int main(){
int t; cin>>t; while(t--){
scanf("%d",&n);
int k=0;
for(int i=0;i<n;i++){
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
q[k++]={x1,y1},q[k++]={x2,y2};
a[i]={x1,y1},b[i]={x2,y2};
}
if(check()) puts("Yes!");
else puts("No!");
}
return 0;
}