POJ 2826 幾何/兩條線段的各種情況。。

題意:給兩個木板,問這兩個木板能接多少水

思路:首先,如果有一個平行於x軸的,或者兩個不相交,或者重合的情況下答案就是0.00。相交的時候分爲兩種情況,一種是斜率不同,這個很好處理,就是較低的點做個平行於x軸的直線,然後圍成的三角形的面積就是答案。如果斜率相同,有如下幾種情況

代碼:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
#include<list>
using namespace std;
const double INF = 1e200;
const double EP = 1e-10;
const int maxn = 4000;
//const double PI = acos(-1);
struct POINT{///點 定義
    double x;
    double y;
    POINT(double a = 0,double b = 0){x = a;y = b;}
};
struct SEGMENT{///line segment///線段 定義
    POINT s;
    POINT e;
    SEGMENT(POINT a,POINT b){s = a;e = b;}
    SEGMENT(){}
};
struct LINE{///ax + by + c = 0&&a >= 0///一般式
    double a;
    double b;
    double c;
    LINE(double da,double db,double dc){a = da;b = db;c = dc;}
    LINE(double x1,double y1,double x2,double y2){///根據兩個點求出一般式
        a = y1 - y2;b = x2 - x1;c = x1*y2 - x2*y1;
        if(a < 0){a*=-1;b*=-1;c*=-1;}
    }
};
double multiply(POINT sp,POINT ep,POINT op){///向量op->sp X op->ep的叉乘,小於0:ep在op->sp順時針方向//大於0:0:ep在op->sp逆時針方向//等於0:三點共線
    return ((sp.x - op.x)*(ep.y - op.y) - (ep.x - op.x)*(sp.y - op.y));
}
double dotmultiply(POINT p1,POINT p2,POINT p0){
    return ((p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y));
}
bool online(SEGMENT l,POINT p){///判斷點是否在線段上
    return ((multiply(l.e,p,l.s) == 0)&&(((p.x-l.s.x)*(p.x-l.e.x))<= 0)&&(((p.y-l.s.y)*(p.y-l.e.y)) <= 0));
}
bool intersect(SEGMENT u,SEGMENT v){///兩線段相交(包括端點),返回true
    return ((max(u.s.x,u.e.x) >= min(v.s.x,v.e.x))&&
            (max(v.s.x,v.e.x) >= min(u.s.x,u.e.x))&&
            (max(u.s.y,u.e.y) >= min(v.s.y,v.e.y))&&
            (max(v.s.y,v.e.y) >= min(u.s.y,u.e.y))&&
            (multiply(v.s,u.e,u.s)*multiply(u.e,v.e,u.s) >= -EP)&&
            (multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s) >= -EP));
}
bool intersect_a(SEGMENT u,SEGMENT v){///兩線段相交(不包括端點)
    return ((intersect(u,v))&&
            !online(u,v.s)&&
            !online(u,v.e)&&
            !online(v,u.e)&&
            !online(v,u.s));
}
int lineintersect(LINE l1,LINE l2,POINT &p){///求兩直線交點,有交點返回1和交點,沒有返回0,重合返回2
    double d = l1.a*l2.b-l2.a*l1.b;
    double d2 = l1.a*l2.c-l2.a*l1.c;
    double d3 = l1.b*l2.c-l2.b*l1.c;
    if(fabs(d) < EP&&fabs(d2) < EP&&fabs(d3) < EP)return 2;
    p.x = (l2.c*l1.b-l1.c*l2.b)/d;
    p.y = (l2.a*l1.c-l1.a*l2.c)/d;
    if(fabs(d) < EP)return 0;
    return 1;
}
double point_dis(POINT a,POINT b){///求兩點距離
    return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
///************************************************************************************************************************************
double dis(POINT a,POINT b){
    double x = a.x - b.x;
    double y = a.y - b.y;
    return sqrt(x*x+y*y);
}
int main(){
    //freopen("in.txt","r",stdin);
    int T;
    cin>>T;
    SEGMENT sa,sb;
    while(T --){
        double x1,y1,x2,y2;
        POINT a,b;
        cin>>x1>>y1>>x2>>y2;
        if(y1 > y2){swap(x1,x2);swap(y1,y2);}
        a.x = x1,a.y = y1;
        b.x = x2,b.y = y2;
        sa.s = a,sa.e = b;

        cin>>x1>>y1>>x2>>y2;
        if(y1 > y2){swap(x1,x2);swap(y1,y2);}
        a.x = x1,a.y = y1;
        b.x = x2,b.y = y2;
        sb.s = a,sb.e = b;
        if(fabs(sa.s.y-sa.e.y) < EP||fabs(sb.s.y - sb.e.y) < EP)puts("0.00");
        else{
            bool flag = intersect(sa,sb);
            if(!flag)puts("0.00");
            else{
                LINE la(sa.s.x,sa.s.y,sa.e.x,sa.e.y),lb(sb.s.x,sb.s.y,sb.e.x,sb.e.y);
                POINT jiao_dian;
                int linn = lineintersect(la,lb,jiao_dian);
                if(linn == 2){puts("0.00");continue;}
                if(la.b*la.a*lb.a*lb.b > 0){///xie lv xiang tong
                    bool ok = 0;
                    if(sa.e.y < sb.e.y){swap(sa,sb);swap(la,lb);}
                    //cout<<la.b*la.a<<endl;
                    if(((la.b/(la.a+EP) - lb.b/(lb.a+EP))*(sa.e.x-sb.e.x)) < 0)ok = 1;
                    if(ok == 1){
                        LINE tmp(sb.e.x,sb.e.y,sb.e.x+10,sb.e.y);
                        POINT point_tmp;
                        lineintersect(tmp,la,point_tmp);
                        double ans = (fabs(point_tmp.x - sb.e.x))*(fabs(jiao_dian.y - sb.e.y));
                        printf("%.2f\n",ans/2.0+EP);//puts("aaaaaaaa");
                    }
                    else puts("0.00");
                }
                else{
                    if(sa.e.y < sb.e.y){swap(sa,sb);swap(la,lb);}
                    LINE tmp(sb.e.x,sb.e.y,sb.e.x+10,sb.e.y);
                    POINT point_tmp;
                    lineintersect(tmp,la,point_tmp);
                    double ans = (fabs(point_tmp.x - sb.e.x))*(fabs(jiao_dian.y - sb.e.y));
                    printf("%.2f\n",ans/2.0+EP);
                }
            }
        }
    }
    return 0;
}

發佈了140 篇原創文章 · 獲贊 5 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章