POJ 3304 Segments(线段相交)

原题链接

Problem Description

Given n segments in the two dimensional space, write a program, which determines if there exists a line such that after projecting these segments on it, all projected segments have at least one point in common.

Input

Input begins with a number T showing the number of test cases and then, T test cases follow. Each test case begins with a line containing a positive integer n ≤ 100 showing the number of segments. After that, n lines containing four real numbers x1 y1 x2 y2 follow, in which (x1, y1) and (x2, y2) are the coordinates of the two endpoints for one of the segments.

Output

For each test case, your program must output “Yes!”, if a line with desired property exists and must output “No!” otherwise. You must assume that two floating point numbers a and b are equal if |a - b| < 10-8.

Sample Input

3
2
1.0 2.0 3.0 4.0
4.0 5.0 6.0 7.0
3
0.0 0.0 0.0 1.0
0.0 1.0 0.0 2.0
1.0 1.0 2.0 1.0
3
0.0 0.0 0.0 1.0
0.0 2.0 0.0 3.0
1.0 1.0 2.0 1.0

Sample Output

Yes!
Yes!
No!

题目大意

原本的题意是给出二维平面内的n条线段,问平面上是否存在一条线,使得这些线段在这条直线上的投影至少有一个公共点。其实这道题可以转换成在平面上是否存在一条直线可以把这些线段全部都串起来。

解题思路

考虑极限情况,如果存在这样的一条直线,就让它穿过某两个线段的端点。由于n的范围很小,可以直接枚举端点,有了端点以后得到直线,再看这根直线和各个线段的相交情况。注意一点,如果两个点之间的距离小于1e-8,则认为这是同一个点,不需要再向下分析。

AC代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
#include<vector>
#include<string>
#include<queue>
#include<list>
#include<stack>
#include<set>
#include<map>
#define ll long long
#define ull unsigned long long
#define rep(i,n) for(int i = 0;i < n; i++)
#define fil(a,b) memset((a),(b),sizeof(a))
#define cl(a) fil(a,0)
#define pb push_back
#define mp make_pair
#define exp 2.7182818
#define PI 3.141592653589793
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define eps 1e-8
#define mod 1000000007ll
#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0)))
using namespace std;
double mysqrt(double x) { return max(0.0, sqrt(x)); }
int sgn(double x)
{
if(fabs(x) < eps)return 0;
if(x < 0)return -1;
else return 1;
}
struct point2
{
    double x,y;
    point2(){}
    point2(double _x,double _y)
    {
        x=_x,y=_y;
    }
    point2 operator-(const point2 &ne)
    {
        return point2(x-ne.x,y-ne.y);
    }
    point2 operator+(const point2 &ne)
    {
        return point2(x+ne.x,y+ne.y);
    }
    point2 operator*(const double t)
    {
        return point2(x*t,y*t);
    }
};
struct line2
{
    point2 a,b;
    line2(){}
    line2(point2 _a,point2 _b)
    {
        a=_a;
        b=_b;
    }
};
double xmult(point2 a,point2 b)
{ 
    return a.x*b.y-a.y*b.x; 
}
double xmult(point2 o,point2 a,point2 b) { return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y); }
double dmult(point2 a,point2 b) { return a.x*b.x+a.y*b.y; } 
double dmult(point2 o,point2 a,point2 b) { return (a.x-o.x)*(b.x-o.x)+(a.y-o.y)*(b.y-o.y); }
inline int seg_inter(line2 s,line2 p) 
{ 
    double minx1=min(s.a.x,s.b.x),maxx1=max(s.a.x,s.b.x); 
    double minx2=min(p.a.x,p.b.x),maxx2=max(p.a.x,p.b.x); 
    double miny1=min(s.a.y,s.b.y),maxy1=max(s.a.y,s.b.y); 
    double miny2=min(p.a.y,p.b.y),maxy2=max(p.a.y,p.b.y); 
    if((minx1>maxx2+eps)||(minx2>maxx1+eps)|| (miny1>maxy2+eps)||(miny2>maxy1+eps)) return 0; 
    else return sign(xmult(s.a,s.b,p.a)*xmult(s.a,s.b,p.b))<=0&& sign(xmult(p.a,p.b,s.a)*xmult(p.a,p.b,s.b))<=0; 
}
double lenth(point2 a){ return sqrt(dmult(a,a)); } 
double dist(point2 a,point2 b){ return lenth(b-a); }
double dist2(point2 a,point2 b){ return dmult(b-a,b-a); }
bool Seg_inter_line(line2 l1,line2 l2) 
{
    return sgn(xmult((l2.a-l1.b),(l1.a-l1.b)))*sgn(xmult((l2.b-l1.b),(l1.a-l1.b))) <= 0;
}
line2 a[105];
point2 b[222];
int main() 
{  
    int t,n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;++i)
        {
            scanf("%lf%lf%lf%lf",&a[i].a.x,&a[i].a.y,&a[i].b.x,&a[i].b.y);
            b[2*i-1].x=a[i].a.x;
            b[2*i-1].y=a[i].a.y;
            b[2*i].x=a[i].b.x;
            b[2*i].y=a[i].b.y;

        }
        if(n==1||n==2) printf("Yes!\n");
        else
        {
        int flag=0;
        for(int i=1;i<2*n&&!flag;++i)
        {
            for(int j=i+1;j<=2*n&&!flag;++j)
            {
                if(dist(b[i],b[j])<eps) continue;
                line2 tmp(b[i],b[j]);
                int fflag=1;
                for(int k=1;k<=n;++k)
                {
                    if(!Seg_inter_line(tmp,a[k])) {fflag=0;break;}
                }
                if(fflag) flag=1;
            }
        }
        if(flag) printf("Yes!\n");
        else printf("No!\n");
        }
    }
    return 0;  
}

猜你喜欢

转载自blog.csdn.net/xj949967574/article/details/70665266