poj 3304 Segments(判断直线与线段相交)

Segments
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 6237   Accepted: 1828

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 (x1y1) and (x2y2) 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!

Source

Amirkabir University of Technology Local Contest 2006
题目: http://poj.org/problem?id=3304
题意:给你n条线段,求是否存在这样一条直线,使得所有线段在直线上的投影有公共部分,至少是一个点
分析:根据题目所求可以转换为求是否存在一条直线与所有线段都相交,这样就可以简单的枚举所有线段的端点,构成的直线,判断该直线是否跟所有线段相交即可,主要是直线与线段相交的模板,呵呵
模板写成这样貌似没有以前精简,不过有利于拓展= =
代码:
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
const int mm=222;
typedef double mType;
struct Tpoint
{
    mType x,y;
    Tpoint(){}
    Tpoint(mType _x,mType _y):x(_x),y(_y){}
};
struct Tsegment
{
    Tpoint a,b;
    Tsegment(){}
    Tsegment(Tpoint _a,Tpoint _b):a(_a),b(_b){}
    Tsegment(mType sx,mType sy,mType tx,mType ty):a(sx,sy),b(tx,ty){}
};
Tpoint MakeVector(Tpoint P,Tpoint Q)
{
    Tpoint tmp=Tpoint(Q.x-P.x,Q.y-P.y);
    return tmp;
}
mType CrossProduct(Tpoint P,Tpoint Q)
{
    return P.x*Q.y-P.y*Q.x;
}
mType MultiCross(Tpoint P,Tpoint Q,Tpoint R)
{
    return CrossProduct(MakeVector(Q,P),MakeVector(Q,R));
}
bool IsLineIntersect(Tsegment P,Tsegment Q)
{
    return (MultiCross(P.b,P.a,Q.a)*MultiCross(P.b,P.a,Q.b)<=0);
}
int i,n,t;
double sx,sy,tx,ty;
Tsegment g[mm];
int count(Tsegment P)
{
    if(fabs(P.a.x-P.b.x)<1e-8&&fabs(P.a.y-P.b.y)<1e-8)return 0;
    int i,ret=0;
    for(i=0;i<n;++i)
        if(IsLineIntersect(P,g[i]))++ret;
    return ret;
}
bool ok()
{
    int i,j;
    Tsegment tmp;
    for(i=0;i<n;++i)
        for(j=i;j<n;++j)
        {
            tmp=Tsegment(g[i].a,g[j].a);
            if(count(tmp)>=n)return 1;
            tmp=Tsegment(g[i].a,g[j].b);
            if(count(tmp)>=n)return 1;
            tmp=Tsegment(g[i].b,g[j].a);
            if(count(tmp)>=n)return 1;
            tmp=Tsegment(g[i].b,g[j].b);
            if(count(tmp)>=n)return 1;
        }
    return 0;
}
void test()
{
    Tsegment tmp=Tsegment(0,0,1,1);
    printf("%.2lf %.2lf %.2lf %.2lf\n",tmp.a.x,tmp.a.y,tmp.b.x,tmp.b.y);
    if(IsIntersect(Tsegment(0,0,0.5,0.499),Tsegment(1,0,0,1)))puts("Yes");else puts("No");
}
int main()
{
    //test();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=0;i<n;++i)
        {
            scanf("%lf%lf%lf%lf",&sx,&sy,&tx,&ty);
            g[i]=Tsegment(sx,sy,tx,ty);
        }
        printf(ok()?"Yes!\n":"No!\n");
    }
    return 0;
}


你可能感兴趣的:(poj 3304 Segments(判断直线与线段相交))