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