POJ2826:计算几何
POJ2826
题解:看似简单的题,却很考验综合能力
容量为0的情况
- 其中一条线段与x轴平行
- 两天线段平行或者重合
- 两条线段无交点
- 有交点,但一条线段的上半部分却覆盖掉了另外一条线段的上半部分。这里需要求斜率。
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;
}

浙公网安备 33010602011771号