poj 3304 Segments

Segments
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 14805 Accepted: 4699

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条线段,求是否存在某一条直线使得所有线段在这条直线上的射影有公共点
其实就是求是否存在一条直线经过所有线段,详情可见:http://blog.sina.com.cn/s/blog_6635898a0100n2lv.html,证明直线经过线段只需证明两端点对直线的叉乘小于0即可,遍历所有端点构成的直线即可

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<cmath>
#include<vector>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;

#define pi acos(-1.0)
#define eps 1e-8//精度要求
#define pf printf
#define sf scanf
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define e tree[rt]
#define _s second
#define _f first
#define all(x) (x).begin,(x).end
#define mem(i,a) memset(i,a,sizeof i)
#define for0(i,a) for(int (i)=0;(i)<(a);(i)++)
#define for1(i,a) for(int (i)=1;(i)<=(a);(i)++)
#define mi ((l+r)>>1)
#define sqr(x) ((x)*(x))

const int inf=0x3f3f3f3f;
int t,m,n;

struct Point
{
    double x,y;
    Point(){}
    Point(int x,int y):x(x),y(y){}
};

struct Line
{
    Point a,b;
}l[110];

double multi(Point a,Point b,Point c)
{
    return (a.x-b.x)*(c.y-b.y)-(a.y-b.y)*(c.x-b.x);//叉乘判断位置
}

bool check(Point a,Point b)//判断传的参数即为要构成直线的两个端点
{
    if(fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps)return 0;//两个点重合
    for0(i,m)//判断所有线段是否满足在直线两侧
        if(multi(l[i].a,a,b)*multi(l[i].b,a,b)>eps)return 0;
    return 1;
}

int main()
{
    sf("%d",&t);
    while(t--)
    {
        sf("%d",&m);
        for0(i,m)
            sf("%lf%lf%lf%lf",&l[i].a.x,&l[i].a.y,&l[i].b.x,&l[i].b.y);
        int flag=false;
        for0(i,m)//遍历所有直线
        {
            if(check(l[i].a,l[i].b))flag=1;
            for(int j=i+1;j<m;j++)
                if(check(l[i].a,l[j].a)||check(l[i].a,l[j].b)||check(l[i].b,l[j].a)||check(l[i].b,l[j].b))
                    flag=1;
        }
        puts(flag?"Yes!":"No!");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值