POJ 3304 Segments(判断直线与线段是否相交)
题目传送门:POJ 3304 Segments
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!
题目大意:
在一个平面上,给你n个线段,问是否存在一条直线,使得将这些线段投影到上面之后,所有投影线段至少有一个共同点。
解题思路:
若存在一条直线使得所有线段投影到上面之后其投影至少有一个公共点,则这条直线必有一条垂线与所有线段都相交。
这题就转化为了求是否存在一条直线与所有线段都相交。
接下来我们只需枚举两个端点(不是同一直线上的)来找这条直线,若所有端点对的直线都不经过所有线段,则不存在这样的直线。
我们的重点就是判断直线与线段是否相交。同时需要注意如果枚举的两个端点相等则为一个点不能确定直线和精度问题(题目说了是10-8)。
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #define eps 1e-8 using namespace std; const int N = 100 + 10; int dcmp(double x) { if(fabs(x)<eps) return 0; return x<0?-1:1; } struct point ///点 { double x, y; point(double a = 0, double b = 0){ x = a, y = b;} point operator-(const point& b) const { return point(x - b.x, y - b.y);} double operator^(const point& b) const { return x * b.y - y * b.x; } } p[2*N]; bool operator == (const point& a, const point& b) { return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0; } struct line ///线 { point s, e; } l[N]; bool Line_Seg(point a1,point a2,line l) { double c1=((a1-a2)^(l.s-a2)),c2=((a1-a2)^(l.e-a2)); return dcmp(c1)*dcmp(c2)<=0; } int num,n,T; bool judge() { for (int i=0; i<num; i++) for (int j=i+1,k; j<num; j++) { if (p[i]==p[j]) continue; for ( k=0; k<n; k++) if (!Line_Seg(p[i],p[j],l[k])) break; if (k>=n) return 1; } return 0; } int main() { for ( scanf("%d",&T); T; T--) { num=0; scanf("%d",&n); for (int i=0; i<n; i++) { scanf("%lf%lf%lf%lf",&l[i].s.x,&l[i].s.y,&l[i].e.x,&l[i].e.y); p[num++]=l[i].s; p[num++]=l[i].e; } if (judge()) printf("Yes!\n"); else printf("No!\n"); } return 0; }