POJ 3304 Segments [计算几何,判断直线和线段相交]

Posted 霜序0.2℃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3304 Segments [计算几何,判断直线和线段相交]相关的知识,希望对你有一定的参考价值。

题目

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!

解释与代码

用了kuangbin的模板,开始一直wa,后来才发现少了两点相同的情况

做法:所有线段中两个不同的点,判断这两点构成的直线能否与所有线段相交(不规范相交也算)

如果不懂原理的可以看看这个:https://zhuanlan.zhihu.com/p/363308561

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <iostream>
#include <sstream>
#include <set>
#include <map>
#include <queue>
#include <bitset>
#include <vector>
#include <limits.h>
#include <assert.h>
#include <functional>
#include <numeric>
#include <ctime>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
#define pb          push_back
#define ppb         pop_back
#define lbnd        lower_bound
#define ubnd        upper_bound
#define endl        '\\n'
#define trav(a, x)  for(auto& a : x)
#define all(a)      (a).begin(),(a).end()
#define F           first
#define S           second
#define sz(x)       (ll)x.size()
#define hell        1000000007
#define DEBUG       cerr<<"/n>>>I'm Here<<</n"<<endl;
#define display(x)  trav(a,x) cout<<a<<" ";cout<<endl;
#define what_is(x)  cerr << #x << " is " << x << endl;
#define ini(a)      memset(a,0,sizeof(a))
#define case        ll T;read(T);for(ll Q=1;Q<=T;Q++)
#define lowbit(x)   x&(-x)
#define pr          printf
#define sc          scanf
//#define _           0
#define FAST ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define DBG(x) \\
    (void)(cout << "L" << __LINE__ \\
    << ": " << #x << " = " << (x) << '\\n')
#define TIE \\
    cin.tie(0);cout.tie(0);\\
    ios::sync_with_stdio(false);
//#define long long int

//using namespace __gnu_pbds;

template <typename T>
void read(T &x) {
    x = 0;
    int f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = x * 10 + (ch ^ 48);
        ch = getchar();
    }
    x *= f;
    return;
}

inline void write(long long x) {
    if(x<0) putchar('-'), x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
    putchar('\\n');
}

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pi    = acos(-1.0);
const double eps   = 1e-8;
const int    INF   = 0x3f3f3f3f;
const ll     LLINF = 0x3f3f3f3f3f3f3f3f;
const int    maxn  = 200009;
const ll     N     = 5;

const double inf=1e20;
const int maxp=1010;

//判断正负
int sgn(double x) {
	if (fabs(x)<eps) return 0;
	if (x<0) return -1;
	else return 1;
}
//平方
inline double sqr(double x) {
	return x*x;
}

struct Point {
	double x,y;
	Point() {}
	Point(double _x, double _y) {
		x=_x;
		y=_y;
	}
	void input() {
		scanf("%lf%lf",&x,&y);
	}
	void output() {
		printf("%.2f%.2f\\n",x,y);
	}
	bool operator == (Point b)const {
		return sgn(x-b.x)==0 && sgn(y-b.y)==0;
	}
	bool operator < (Point b)const {
		return sgn(x-b.x)==0?sgn(y-b.y)<0:x<b.x;
	}
	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;
	}
	//点积
	double operator *(const Point &b)const {
		return x*b.x+y*b.y;
	}
	//返回长度
	double len() {
		return hypot(x,y);
	}
	//返回长度平方
	double len2() {
		return x*x+y*y;
	}
	//返回两点间距
	double distance(Point p) {
		return hypot(x-p.x,y-p.y);
	}
	Point operator +(const Point &b)const {
		return Point(x+b.x,y+b.y);
	}
	Point operator *(const double &k)const {
		return Point(x*k,y*k);
	}
	Point operator /(const double &k)const {
		return Point(x/k,y/k);
	}
	//pa和pb的夹角
	double rad(Point a,Point b) {
		Point p=*this;
		return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p)));
	}
	//化为长度为r的向量
	Point trunc(double r) {
		double l=len();
		if (!sgn(l)) return *this;
		r/=l;
		return Point(x*r,y*r);
	}
	//逆时针旋转 90 度
	Point rotleft() {
		return Point(-y,x);
	}
	//顺时针旋转 90 度
	Point rotright() {
		return Point(y,-x);
	}
	//绕着 p 点逆时针旋转 angle
	Point rotate(Point p,double angle) {
		Point v=(*this)-p;
		double c=cos(angle),s=sin(angle);
		return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
	}
};


struct Line {
	Point s,e;
	Line() {}
	Line(Point _s,Point _e) {
		s=_s;
		e=_e;
	}
	bool operator ==(Line v) {
		return (s==v.s) && (e==v.e);
	}
	//根据一个点和倾斜角 angle 确定直线,0<=angle<π
	Line(Point p, double angle) {
		s=p;
		if (sgn(angle-pi/2)==0) {
			e=(s+Point(0,1));
		} 
		else {
			e=(s+Point(1,tan(angle)));
		}
	}
	//ax+by+c=0
	Line(double a,double b,double c) {
		if(sgn(a)==0) {
			s=Point(0,-c/b);
			e=Point(1,-c/b);
		} 
		else if(sgn(b)==0) {
			s=Point(-c/a,0);
			e=Point(-c/a,1);
		} 
		else {
			s=Point(0,-c/b);
			e=Point(1,(-c-a)/b);
		}
	}
	void input() {
		s.input();
		e.input();
	}
	void adjust() {
		if(e<s) swap(s,e);	
	}
	//求线段长度
	double length() {
		return s.distance(e);
	}
	//返回直线倾斜角 0<=angle<π 
	double angle() {
		double k=atan2(e.y-s.y,e.x-s.x);
		if(sgn(k)<0) k+=pi;
		if(sgn(k-pi)==0) k-= pi;
		return k;
	}
	//点和直线关系
	// 1 在左侧
	// 2 在右侧
	// 3 在直线上 
	int relation(Point p) {
		int c=sgn((p-s)^(e-s));
		if(c<0) return 1; 
		else if(c>0) return 2; 
		else return 3;	 
	}
	//点在线段上的判断
	bool pointonseg(Point p) {
		return sgn((p-s)^(e-s))==0 && sgn((p-s)*(p-e))<=0;
	}
	//两向量平行 (对应直线平行或重合)
	bool parallel(Line v) {
		return sgn((e-s)^(v.e-v.s))==0;
	}
	//两线段相交判断
	//2 规范相交
	//1 非规范相交
	//0 不相交
	int segcrossseg(Line v) {
		int d1=sgn((e-s)^(v.s-s));
		int d2=sgn((e-s)^(v.e-s));
		int d3=sgn((v.e-v.s)^(s-v.s));
		int d4=sgn((v.e-v.s)^(e-v.s));
		if((d1^d2)==-2&&(d3^d4)==-2)return 2;
		return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) ||
		       (d2==0 && sgn((v.e-s)*(v.e-e))<=0) ||
		       (d3==0 && sgn((s-v.s)*(s-v.e))<=0) ||
		       (d4==0 && sgn((e-v.s)*(e-v.ePOJ-3304Segments[计算几何]

POJ 3304 Segments [计算几何,判断直线和线段相交]

POJ 3304 Segments(计算几何:直线与线段相交)

POJ3304 Segments 线段直线相交

POJ 3304 Segments(判断直线与线段是否相交)

poj3304计算几何直线与线段关系