POJ 2826 An Easy Problem?!(线段关系)

五迷三道 提交于 2019-11-26 16:36:30
  • 题意: 给出两根木棍,求最多能接到多少水
  • 思路: 疯狂判断 1. 判断两个线段是否平行 2. 判断是否有交点 3. 求交点和较短木棍的点 4. 判断斜率大的直线会不会覆盖斜率小的直线

\(dis(e,d)>dis(c,d)\)即可

#include<string>
#include<vector>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#define ll long long
#define FOR(i,l,r) for(int i = l ; i <= r ;++i )
using namespace std;
const int maxn = 101;
const double eps =  1e-6;
int sgn(double k){
    if(fabs(k)<eps) return 0;
    if(k>0) return 1;
    return -1;
}

struct point{
    double x,y;
    point(){}
    point(double _x,double _y):x(_x),y(_y){}
    void input(){
        scanf("%lf%lf",&x,&y);
    }
    point operator - (point b){
        return point(x-b.x,y-b.y);
    }
};
struct line{
    point a,b;
    line(){}
    line(point a,point b):a(a),b(b){}
};

double det(point a,point b){
    return a.x * b.y - b.x * a.y;
}

bool segcorseg(line l1,line l2){
    return sgn(det(l1.a-l2.a,l1.b-l2.a))*sgn(det(l1.a-l2.b,l1.b-l2.b))<=0
    && sgn(det(l2.a-l1.a,l2.b-l1.a))*sgn(det(l2.a-l1.b,l2.b-l1.b))<=0;
}
point crosspoint(line l1,line l2){
    double a1 = det(l2.b-l2.a,l1.a-l2.a);
    double a2 = det(l2.b-l2.a,l1.b-l2.a);
    return point((l1.a.x*a2-l1.b.x*a1)/(a2-a1),(l1.a.y*a2-l1.b.y*a1)/(a2-a1));
}
bool parallel(line l1,line l2){
    return sgn(det(l1.b-l1.a,l2.b-l2.a))==0;
}
bool pointonline(point a,line l){
    return sgn(det(l.a-a,l.b-a))==0;
}
double dist(point a,point b){
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
bool check(line l1,line l2){
    double x1 = (l1.a.y - l1.b.y)/(l1.a.x-l1.b.x);
    double x2 = (l2.a.y - l2.b.y)/(l2.a.x-l2.b.x);
    if(sgn(x1)==sgn(x2)){
        if(fabs(x1)>fabs(x2)){
            point a= crosspoint(l2,line(l1.b,point(l1.b.x,0)));
            if(sgn(dist(a,l2.a)-dist(l2.a,l2.b))>=0) 
                return 0;
        }else{
            point a= crosspoint(l1,line(l2.b,point(l2.b.x,0)));
            if(sgn(dist(a,l1.a)-dist(l1.a,l1.b))>=0) 
                return 0;
        }
    }
    return 1;
}
int n;
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        point a,b;
        double ans = 0.0;
        line l1,l2;
        a.input(); b.input();
        if(a.y>b.y) swap(a,b);
        l1 = line(a,b);
        a.input(); b.input();
        if(a.y>b.y) swap(a,b);
        l2 = line(a,b);
        if(!parallel(l1,l2) && segcorseg(l1,l2)){
            a = crosspoint(l1,l2);
            if(pointonline(a,l1) && pointonline(a,l2)){
                double y1 = max(l1.a.y,l1.b.y);
                y1 = min(y1,max(l2.a.y,l2.b.y));
                line l3 = line(point(0,y1),point(10000,y1));
                if(!parallel(l1,l3) && !parallel(l2,l3)){
                    if(check(l1,l2)){
                        point c = crosspoint(l1,l3);
                        point d = crosspoint(l2,l3);
                        ans = fabs(c.x-d.x)*fabs(y1-a.y)*0.5;
                    }
                }
            }
        }
        printf("%.2lf\n",ans+eps);
    }
    return 0;
}

精度可以调小一点,1e4的数据会有精度误差

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!