Segments
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 15777 Accepted: 5011
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!
Source
Amirkabir University of Technology Local Contest 2006
做法:假设存在这么一条直线,则过所有线段在这条直线上的投影的交集上任意一点做直线的垂线,那么这个垂线一定和所有直线相交,问题就转换成了是否存在一条直线与所有线段相交。且投影的两端肯定是由某线段或某两个线段的端点投影而来的,枚举端点,看形成的直线和所有线段是否有交即可。
**判断直线与线段相交的方法:
直线和线段有交点肯定是线段的两个端点不在直线的同侧
也就是说两个端点分别和直线的叉积,乘起来是<=0的,利用这个特性我们可以判断它们的关系**
注意:这道题会出现直线的两端在同一个点的情况,遇到这种情况肯定就是 No!了,我们就要判断一下两个端点的距离是不是小于eps,是的话就是重合了。
PS:求叉积double写成int,GG……..
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <vector>
#define maxn 10010
#define maxe 100010
typedef long long ll;
using namespace std;
const double eps=1e-8;
const int inf=0x3f3f3f3f3f;
int sgn(double x)
{
if(fabs(x) < eps)return 0;
if(x < 0) return -1;
return 1;
}
struct Point
{
double x,y;
Point(){};
Point(double a,double b)
{
x=a,y=b;
}
void input()
{
scanf("%lf%lf",&x,&y);
}
Point operator +(Point a)
{
Point b(x+a.x,y+a.y);
return b;
}
Point operator -(Point a)
{
Point b(x-a.x,y-a.y);
return b;
}
double operator *(Point a)
{
return x*a.x+y*a.y;
}
double operator ^(Point a)
{
return x*a.y-y*a.x;
}
bool operator <(Point a)
{
return x<a.x;
}
double len()
{
return sqrt(x*x+y*y);
}
};
double mul(Point p0,Point p1,Point p2)
{
return (p1-p0)^(p2-p0);
}
double dis(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
struct Line
{
Point a,b;
double k,d;
bool flag;
void prepare()
{
if(a.x-b.x!=0)
k=(a.y-b.y)*1.0/(a.x-b.x),flag=true,d=a.y-k*a.x;
else flag=false,d=a.x;
}
Line(Point st,Point ed)
{
a=st;
b=ed;
prepare();
}
Line(){};
void input()
{
a.input();
b.input();
prepare();
}
int operator *(Line l)
{
return (a-b)*(l.a-l.b);
}
int operator ^( Line l)
{
return (a-b)^(l.a-l.b);
}
Point intersect(Line l)
{
Point r;double x,y;
if(!flag&&l.flag)
{
x=d;
y=l.k*x+l.d;
}
else if(flag&&!l.flag)
{
x=l.d;
y=k*x+d;
}
else
{
x=(l.d-d)/(k-l.k);
y=k*x+d;
}
r.x=x;
r.y=y;
return r;
}
}l[maxn];
//line l1,segment l2
bool check(Line l1,Line l2)
{
return sgn(mul(l2.a,l1.a,l1.b))*sgn(mul(l2.b,l1.a,l1.b))<=0;
}
bool judge(Line l1,int n)
{
if(sgn(dis(l1.a,l1.b))==0)return false;
for(int i=0;i<n;i++)
{
if(check(l1,l[i])==false)
return false;
}
return true;
}
int main()
{
int t;
int n;
//freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
l[i].input();
}
bool flag=false;
for(int i=0;i<n&&!flag;i++)
for(int j=0;j<n&&!flag;j++)
if(judge(Line(l[i].a,l[j].a),n) || judge(Line(l[i].a,l[j].b),n)
|| judge(Line(l[i].b,l[j].a),n) || judge(Line(l[i].b,l[j].b),n) )
{
flag=true;
break;
}
if(flag)
printf("Yes!\n");
else printf("No!\n");
}
return 0;
}