POJ 3304 - Segments【计算几何 - 直线线段相交判断】

来源:互联网 发布:2016淘宝有前景的类目 编辑:程序博客网 时间:2024/04/30 19:41

Segments

Time Limit: 1000MSMemory Limit: 65536KB

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 x1y1x2y2 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条线段的两端点坐标,求是否存在一条直线,使所有线段到这条直线的投影至少有一个交点。


算法分析:
若存在一条直线l和所有线段相交,过投影相交区域作直线的垂线,该垂线必定与每条线段相交,问题转化为问是否存在一条线和所有线段相交直线肯定经过两个端点。从而将题目简化成枚举端点,判断直线和线段是否相交的问题!

代码实现:

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#include <math.h>#include <map>#include <queue>#include <vector>#include <stack>using namespace std;const double eps = 1e-8;const int Max = 105;int n;struct Point{    double x, y;    Point(double x = 0, double y = 0) : x(x), y(y){ }}s[Max], e[Max];typedef Point Vector;Vector operator - (Vector A, Vector B)   { return Vector(A.x - B.x, A.y - B.y); }double Cross(Vector A, Vector B)///叉积计算{    return A.x * B.y - A.y * B.x;}double Area2(Point A, Point B, Point C){    return Cross(A - C, B - C);}bool solve(Point a, Point b){    if(fabs(a.x - b.x) < eps && fabs(a.y - b.y) < eps)        return false;    for(int i = 0; i < n; i++)        if(Area2(a,b,s[i]) * Area2(a,b,e[i]) > eps)///叉积判断两个点是否在同一侧,在返回false,不再返回false            return false;    return true;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(int i = 0; i < n; i++)            scanf("%lf %lf %lf %lf",&s[i].x,&s[i].y,&e[i].x,&e[i].y);        int ans = 0;        if(n < 3)            ans = 1;        for(int i = 0; i <  n && !ans; i++)///枚举线段端点判断是否存在直线        for(int j = i + 1; j < n && !ans; j++)        {            if(solve(s[i],s[j]))    ans = 1;            else if(solve(s[i],e[j]))    ans = 1;            else if(solve(e[i],s[j]))    ans = 1;            else if(solve(e[i],e[j]))    ans = 1;        }        if(ans)            printf("Yes!\n");        else            printf("No!\n");    }    return 0;}


0 0
原创粉丝点击