poj3304 Segments

Segments
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 15967   Accepted: 5063

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

大致题意:给一些线段,问有没有一条直线,使得这些线段的投影在直线上有公共点.
分析:投影实际上就是做垂线,如果一条直线穿过所有线段,做这条直线的垂线,垂足就是公共点.这是问题的第一步转化.那么这条直线怎么求呢?两点确定一条直线,这个点有无穷多个,不太好确定.事实上这两个点可以由线段的任意两个端点确定.为什么呢.假设一条直线穿过了所有的线段,每条线段就是阻碍点.直线可以在线段上自由挪动,旋转,直到碰到阻碍点.感性地理解一下,如果一条直线穿过两个端点并且穿过所有线段,那么它就是满足条件的,不会有这种情况:没有穿过两个端点的直线穿过所有线段,却有穿过所有线段的直线.那么就很好做了,枚举两个端点,利用叉积判断.
           坑点:n = 1特判掉.
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int T,n;
bool flag = false;
const double eps = 1e-8;

struct node
{
    double x,y;
};

struct node2
{
    node p1,p2;
}e[110];

node sub(node a,node b)
{
    node temp;
    temp.x = a.x - b.x;
    temp.y = a.y - b.y;
    return temp;
}

double det(node a,node b)
{
    return a.x * b.y - a.y * b.x;
}

void check(node a,node b)
{
    if (sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) < eps)
        return;
    for (int i = 1; i <= n; i++)
    {
        double temp1 = det(sub(b,a),sub(e[i].p1,a));
        double temp2 = det(sub(b,a),sub(e[i].p2,a));
        if (temp1 * temp2 > eps)
            return;
    }
    flag = true;
}

int main()
{
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);
        flag = false;
        for (int i = 1; i <= n; i++)
            scanf("%lf%lf%lf%lf",&e[i].p1.x,&e[i].p1.y,&e[i].p2.x,&e[i].p2.y);
        if (n <= 2)
        {
            puts("Yes!");
            continue;
        }
        for (int i = 1; i <= n; i++)
        {
            for (int j = i + 1; j <= n; j++)
            {
                check(e[i].p1,e[j].p1);
                check(e[i].p1,e[j].p2);
                check(e[i].p2,e[j].p1);
                check(e[i].p2,e[j].p2);
                if (flag)
                    break;
            }
            if (flag)
                break;
        }
        if (flag)
            puts("Yes!");
        else
            puts("No!");
    }

    return 0;
}

 

posted @ 2017-12-24 15:58  zbtrs  阅读(163)  评论(0编辑  收藏  举报