题目大意:给出一些线段,然后判断这些线段的投影是否有可能存在一个公共点。
分析:如果这些线段的投影存在一个公共点,那么过这个公共点作垂线一定与所有的直线都想交,于是题目转化成是否存在一个直线可以经过所有的线段,考虑线段并不多,所以可以枚举任意两点当作直线......
代码如下:
=============================================================================================================================
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std; const int MAXN = ;
const double ESP = 1e-; struct Point
{
double x, y; Point(double x=, double y=):x(x), y(y){}
Point operator + (const Point &tmp) const{
return Point(x+tmp.x, y+tmp.y);
}
Point operator - (const Point &tmp) const{
return Point(x-tmp.x, y-tmp.y);
}
bool operator ==(const Point &tmp) const{
return (fabs(x-tmp.x) < ESP) && (fabs(y-tmp.y) < ESP);
}
int operator * (const Point &tmp) const{
double t = x*tmp.y - y*tmp.x; if(t > ESP)return ;
if(fabs(t) < ESP)return ;
return -;
}
};
struct Segment
{
Point A, B;
Segment(Point t1=, Point t2=){A=t1, B=t2;}
};
bool Find(Segment t, Segment seg[], int N)
{
for(int i=; i<=N; i++)
{///使用叉积判断是否想交
int k = fabs((t.A-t.B)*(seg[i].A-t.B) + (t.A-t.B)*(seg[i].B-t.B)); if(k==)return false;
} return true;
} int main()
{
int N, T; scanf("%d", &T); while(T--)
{
double x1, x2, y1, y2;
Point p[MAXN];
Segment seg[MAXN]; scanf("%d", &N); int M=; for(int i=; i<=N; i++)
{
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
p[M++]=Point(x1, y1), p[M++]=Point(x2, y2);
seg[i]=Segment(p[M-], p[M-]);
} int ok = false; for(int i=; i<M && !ok; i++)
for(int j=i+; j<M && !ok; j++)
{
if(p[i] == p[j])
continue; ok = Find(Segment(p[i], p[j]), seg, N);
} if(ok)printf("Yes!\n");
else printf("No!\n");
} return ;
}