zoukankan      html  css  js  c++  java
  • 判断平面上是否有一条直线与所有线段相交

    poj 3304

    #include<iostream>
    #include<algorithm>
    #include<cmath> 
    #include<cstdio>
    using namespace std;
    #define ll long long
    const int N = 200+10;
    const int maxp = 1010;
    const double eps = 1e-8;//精度
    const double inf = 1e20;
    const double pi = acos(-1.0);
    int sgn(double x)
    {
    	if(fabs(x) < eps)
    		return 0;
    	if(x < 0)
    		return -1;
    	else
    		return 1;
    }
    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
    ",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 的夹角`
    	//`就是求这个点看a,b 所成的夹角`
    	//`测试 LightOJ1203`
    	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<pi`
    	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<pi`
    	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.e))<=0);
    	}
    	//`直线和线段相交判断`
    	//`-*this line   -v seg`
    	//`2 规范相交`
    	//`1 非规范相交`
    	//`0 不相交`
    	int linecrossseg(Line v){
    		int d1 = sgn((e-s)^(v.s-s));
    		int d2 = sgn((e-s)^(v.e-s));
    		if((d1^d2)==-2) return 2;
    		return (d1==0||d2==0);
    	}
    	//`两直线关系`
    	//`0 平行`
    	//`1 重合`
    	//`2 相交`
    	int linecrossline(Line v){
    		if((*this).parallel(v))
    			return v.relation(s)==3;
    		return 2;
    	}
    	//`求两直线的交点`
    	//`要保证两直线不平行或重合`
    	Point crosspoint(Line v){
    		double a1 = (v.e-v.s)^(s-v.s);
    		double a2 = (v.e-v.s)^(e-v.s);
    		return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
    	}
    	//点到直线的距离
    	double dispointtoline(Point p){
    		return fabs((p-s)^(e-s))/length();
    	}
    	//点到线段的距离
    	double dispointtoseg(Point p){
    		if(sgn((p-s)*(e-s))<0 || sgn((p-e)*(s-e))<0)
    			return min(p.distance(s),p.distance(e));
    		return dispointtoline(p);
    	}
    	//`返回线段到线段的距离`
    	//`前提是两线段不相交,相交距离就是0了`
    	double dissegtoseg(Line v){
    		return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v.dispointtoseg(s),v.dispointtoseg(e)));
    	}
    	//`返回点p在直线上的投影`
    	Point lineprog(Point p){
    		return s + ( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) );
    	}
    	//`返回点p关于直线的对称点`
    	Point symmetrypoint(Point p){
    		Point q = lineprog(p);
    		return Point(2*q.x-p.x,2*q.y-p.y);
    	}
    };
    Line line[1005];
    int n;
    int check(Point s,Point e)
    {
    	Line l1 = Line(s,e);
    	if(sgn(l1.length()) == 0)
    		return 0;
    	for(int i=1;i<=n;i++)
    	{	
    
    		if(l1.linecrossseg(line[i]) == 0)
    		{
    			return 0; 
    		}
    	}
    	return 1;
    }
    void solve()
    {
    	
    	cin >> n;
    	for(int i=1;i<=n;i++)
    	{
    		line[i].input();
    	}
    	int flag = 0;
    	for(int i=1;i<=n;i++)
    	{		
    		if(flag == 1)
    			break;
    		for(int j=1;j<=n;j++)
    		{
    			if(check(line[i].s,line[j].s) || check(line[i].s,line[j].e) || 
    			check(line[i].e,line[j].s) || check(line[i].e,line[j].e))
    			{
    				flag = 1;
    				break;
    			}
    		}
    
    	}
    	if(flag)
    	{
    		puts("Yes!");
    	}
    	else
    	{
    		puts("No!");
    	}
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		solve();
    	}
        return 0;
    }
    
    
  • 相关阅读:
    GetHub下载不成功
    Cache 判断Ip几分钟内攻击次数
    .net 通过Url获取站点json数据
    Linq 读取Xml 数据
    ef Linq 自定义字段列表
    面试的心得
    触发器--单独字段变化另一个字段也变化
    Ajax跨域 取值 Jsonp的定义注意事项
    asp.net里,各种下载方式汇总
    c# 获取硬件信息
  • 原文地址:https://www.cnblogs.com/hh13579/p/13828079.html
Copyright © 2011-2022 走看看