POJ2826:计算几何

POJ2826

题解:看似简单的题,却很考验综合能力

容量为0的情况

  1. 其中一条线段与x轴平行
  2. 两天线段平行或者重合
  3. 两条线段无交点
  4. 有交点,但一条线段的上半部分却覆盖掉了另外一条线段的上半部分。这里需要求斜率。

C++AC,G++WA的代码

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
double const eps = 1e-8;
typedef struct Point{   //点和向量
	double x,y;
	Point(){};
	Point(double x,double y):x(x),y(y){};
	Point operator - (const Point& e)const{   //减
		return Point(x - e.x,y - e.y);
	}
	Point operator + (const Point& e)const{
		return Point(x + e.x,y + e.y);
	}
	double operator ^ (const Point& e)const{  //叉乘
		return x * e.y - y * e.x;
	}
}Vector;
struct Line{    //直线的定义
	Point a,b;
	Line(){};
	Line(Point a,Point b):a(a),b(b){}
}l1,l2;
Line X = Line(Point(0,0),Point(1,0));   //表示x轴
int dcmp(double x){    //判断符号
	if(fabs(x) < eps)	return 0;
	else return x < 0 ? -1 : 1;
}
bool onsegment(Point p,Point a1,Point a2){
	return dcmp((a1 - p) ^ (a2 - p)) == 0 && dcmp((a1 - p) * (a2 - p)) <= 0;  
}
bool segment_intersection(Line line1,Line line2){  //判断线段是否相交,相交返回true
	double c1 = (line1.b - line1.a) ^ (line2.a - line1.a);
	double c2 = (line1.b - line1.a) ^ (line2.b - line1.a);
	double c3 = (line2.b - line2.a) ^ (line1.a - line2.a);
	double c4 = (line2.b - line2.a) ^ (line1.b - line2.a);
	if(dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0)	return true;
	if(onsegment(line1.a,line2.a,line2.b) || onsegment(line1.b,line2.a,line2.b))	return true;
	if(onsegment(line2.a,line1.a,line1.b) || onsegment(line2.b,line1.a,line1.b))	return true;
}
bool parallel(Line line1,Line line2){   //平行或者重合
	return ((line1.b - line1.a) ^ (line2.b - line2.a)) == 0;
}
Point intersection(Point p,Vector v,Point q,Vector w){   //两直线(p+tv)和(q+tw)求交点
	Vector u = p - q;
	double t = (w ^ u) / (v ^ w);
	return p + Point(v.x * t,v.y * t);
}
double solve(Line line1,Line line2){
	if(parallel(line1,line2) || !segment_intersection(line1,line2))	return 0;  //平行或重合或者无交点
	if(parallel(line1,X) || parallel(line2,X))	return 0;	//某一条与X轴平行
	double k1 = atan2(line1.b.y - line1.a.y,line1.b.x - line1.a.x);//atan2求斜率,可以处理平行y轴的情况
	double k2 = atan2(line2.b.y - line2.a.y,line2.b.x - line2.a.x);
	if(dcmp(k1 * k2) > 0){   //长的线段覆盖住短的上半部分
		if(dcmp(k1 - k2) > 0 && dcmp(line1.b.x - line2.b.x) >= 0)	return 0;
		if(dcmp(k2 - k1) > 0 && dcmp(line2.b.x - line1.b.x) >= 0)	return 0;
	}
	if(line2.b.y < line1.b.y) swap(line1,line2);
	Line line3 = Line(line1.b,Point(line1.b.x + 1,line1.b.y));
	Point p1 = intersection(line1.a,line1.b - line1.a,line2.a,line2.b - line2.a);	
	Point p2 = intersection(line3.a,line3.b - line3.a,line2.a,line2.b - line2.a);
	return fabs((line1.b - p1) ^ (p2 - p1)) / 2;
}
int main(){
	int T;
	scanf("%d",&T); 
	while(T--){
		scanf("%lf%lf%lf%lf",&l1.a.x,&l1.a.y,&l1.b.x,&l1.b.y);
		scanf("%lf%lf%lf%lf",&l2.a.x,&l2.a.y,&l2.b.x,&l2.b.y);
		if(l1.a.y > l1.b.y) swap(l1.a,l1.b);
		if(l2.a.y > l2.b.y) swap(l2.a,l2.b);
		printf("%.2f\n",solve(l1,l2));
	}
	return 0;
}

 

posted @ 2019-03-31 16:22  月光下の魔术师  阅读(11)  评论(0)    收藏  举报