POJ 3304 Segments (+ thinking and judgment straight line segments intersecting relationship)

Topic Link

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.

1. Title is simple: a given segment n, determines whether there is a two-dimensional coordinate system such that all straight line segments to meet projected on the straight line intersects at least one point

2. Think about the first draw a straight line, and assuming the worst case, if all the projected only one point, just a few construction segment, you will find there is a line at the end of a straight line through the projected point. And then expanded into a period of repeated projection segment, and configured to meet the conditions of some of the line segments, the line segment end points can be found that the two straight lines through all the line segments. And given the number of segments is not a lot, bold speculation enumerate any direct straight line composed of two endpoints whether to go through all segments

3. The method of determining the line and straight lines intersect, is a quick rejection test, I calculate the entry geometry concluding there is a straight line and a variety of issues blog , the biggest pit this question is that there may be segments share an endpoint, we know enumerate special judge whether the two must repeat the point, but the following method is clearly not, because it is not only to ensure that the enumeration itself, but also behind repeated point that may occur using this method unless discrete

for(int i=0;i<num && !flag;i++)
	for(int j=0;j<i && !flag;j++)

Code:

#include <iostream>
#include <math.h>
using namespace std;
#define Point Vector
#define Line Seg
const double eps=1e-8;

int dcmp(double d){
    if(fabs(d)<eps) return 0;
    if(d>0) return 1;
    return -1;
}

struct Point{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y){}
    Point operator + (Point p){ return Point(x+p.x,y+p.y); }
    Point operator - (Point p){ return Point(x-p.x,y-p.y); }
    Point operator * (double d){ return Point(x*d,y*d); }
    double operator * (Point p){ return x*p.x+y*p.y; }
    Point operator / (double d){ return Point(x/d,y/d); }
    double operator ^ (Point p){ return x*p.y-y*p.x; }
    bool operator == (const Point &p) const { return dcmp(x-p.x)==0 && dcmp(y-p.y)==0; }
};

double dis(Point a,Point b){
    return sqrt((b-a)*(b-a));
}

struct Line{
    Point p,q;
    Vector v;
    Line(){}
    Line(Point a,Point b){
        p=a,q=b,v=b-a;
    }
};

bool isOnLine(Point p,Line l){
    return dcmp((l.p-p)^(l.q-p))==0?true:false;
}

bool isSegLineInter(Seg s,Line l){
    double c1=l.v^(s.p-l.p),c2=l.v^(s.q-l.p);
    return dcmp(c1)*dcmp(c2)<=0;
}

Point t[1005];
Seg s[200];

int main()
{
    int kase,n;
    double a,b,c,d;
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>kase;
    while(kase--){
        cin>>n;
        int num=0,cnt=0;
        Point aa,bb;
        while(n--){
            cin>>a>>b>>c>>d;
            aa=Point(a,b),bb=Point(c,d);
            t[num++]=aa;
            t[num++]=bb;
            s[cnt++]=Line(aa,bb);
        }
        int flag=0;
        for(int i=0;i<num && !flag;i++){
            for(int j=0;j<num && !flag;j++){
                if(dcmp(dis(t[i],t[j]))==0) continue;  //坑!!!
                flag=1;
                Line l=Line(t[i],t[j]);
                for(int k=0;k<cnt;k++){
                    if(!isSegLineInter(s[k],l)){
                        flag=0;
                        break;
                    }
                }
            }
        }
        if(flag) cout<<"Yes!\n";
        else cout<<"No!\n";
    }

    return 0;
}
Published 127 original articles · won praise 7 · views 5238

Guess you like

Origin blog.csdn.net/qq_44691917/article/details/104824049