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;
}
posted @ 2021-02-14 21:42  ans20xx  阅读(34)  评论(0编辑  收藏  举报