poj2826

题目
题意:两条直线组成一个图形,能装多少雨水。
思路:如果可以,就会围成一个三角形。两条边的最高点 中 低点的y坐标为围成的三角形的上边的y坐标,再求出交点坐标,求面积。(不看讨论区真做不出来)。

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#define ll long long
#define llu unsigned long long
using namespace std;
const double eps = 1e-8;
struct Point {
    double x,y;
    Point (double x = 0,double y = 0) : x(x),y(y) {}
};
Point a,b,c,d;
bool dcmp(double x) {
    if(fabs(x)-0.0 <= eps) return true;
    return false;
}

double cross(Point a,Point b,Point c) {
    if(dcmp(((b.x-a.x)*(c.y-a.y)) - ((c.x-a.x)*(b.y-a.y)))) return 0;  //卡精度!!!
    return ((b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y));
}

bool pdC(Point a,Point b,Point c,Point d)  {  //判断两线是否重合
    if((dcmp(a.x-c.x)&&(dcmp(a.y-c.y)) && (dcmp(b.x-d.x))&&dcmp(b.y-d.y))
       || (dcmp(a.x-d.x)&&(dcmp(a.y-d.y)) && (dcmp(b.x-c.x))&&dcmp(b.y-c.y))) return true;
    return false;
}
bool pdJ(Point a,Point b,Point c,Point d) {  //判断是否相交
    if(min(a.x,b.x) <= max(c.x,d.x) && min(c.x,d.x) <= max(a.x,b.x) 
    && min(a.y,b.y) <= max(c.y,d.y) && min(c.y,d.y) <= max(a.y,b.y)) {
            if(cross(a,b,c)*cross(a,b,d) <= 0 && cross(c,d,a)*cross(c,d,b) <= 0) {
                return true;
            }
       }
    return false;
}
bool pdP(Point a,Point b) {     // 判断是否和x轴平行
    if(dcmp(a.y - b.y)) return true;
    return false;
}
bool pdT(Point a,Point b) {    //判断线为点
    if(dcmp(a.x-b.x) && dcmp(a.y-b.y)) return true;
    return false;
}
double Pd(Point a,Point b,Point c,Point d) {  //求面积  (判断有一个垂直x轴)
    if(dcmp(a.x-b.x) && dcmp(c.x-d.x)) {
        return 0;
    }
    else if(dcmp(a.x-b.x)) {    //垂直x轴
        double t1 = ((c.y-d.y)/(c.x-d.x));
        Point z1,z2;
        if(c.y>d.y) z2 = c;
        else z2 = d;
        if(a.y > b.y) z1 = a;
        else z1 = b;
        double Maxy = min(z1.y,z2.y);
        Point ji;
        ji.x = a.x;
        ji.y = t1*a.x - t1*c.x + c.y;
        double lx = (Maxy - c.y+t1*c.x)/t1;
        return (fabs(lx-a.x))*(Maxy-ji.y)/2;
    }
    else if(dcmp(c.x-d.x)) {
        double t1 = ((a.y-b.y)/(a.x-b.x));
        Point z1,z2;
        if(c.y>d.y) z2 = c;
        else z2 = d;
        if(a.y > b.y) z1 = a;
        else z1 = b;
        double Maxy = min(z1.y,z2.y);
        Point ji;
        ji.x = c.x;
        ji.y = t1*c.x - t1*a.x+a.y;
        double lx = (Maxy - a.y+t1*a.x)/t1;
        return (fabs(lx-c.x))*(Maxy-ji.y)/2;
    }
    else {
        double t1 = ((a.y-b.y)/(a.x-b.x));
        double t2 = ((c.y-d.y)/(c.x-d.x));
        if(dcmp(t1-t2)) return 0;
        Point z1,z2;
        if(c.y > d.y) z2 = c;
        else z2 = d;
        if(a.y > b.y) z1 = a;
        else z1 = b;
        if(t1*t2 > 0) {
            if(t1 > t2) {
                if(z1.x-z2.x >= 0) return 0;
            }
            if(t2 > t1) {
                if(z2.x-z1.x >= 0) return 0;
            }
        }
        double Maxy = min(z1.y,z2.y);
        Point ji;
        double Maxx1 = (Maxy-a.y+t1*a.x)/t1;
        double Maxx2 = (Maxy-c.y+t2*c.x)/t2;
        ji.x = (t1*a.x-t2*c.x+c.y-a.y)/(t1-t2);
        ji.y = t1*ji.x-t1*a.x+a.y;
        return (fabs(Maxx2-Maxx1)*(Maxy-ji.y))/2;
    }
}
int main(){

    int t; scanf("%d",&t);
    while(t--) {
        scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
        scanf("%lf%lf%lf%lf",&c.x,&c.y,&d.x,&d.y);
        if(pdT(a,b) || pdT(c,d)) {    //线为点
            printf("0.00\n"); continue;
        }
        if(pdC(a,b,c,d)) {      //重合
            printf("0.00\n"); continue;
        }
        if(!pdJ(a,b,c,d)) {     //相交
            printf("0.00\n"); continue;
        }
        if(pdP(a,b) || pdP(c,d)) { // 平行x轴
            printf("0.00\n"); continue;
        }
        double s;
        s = Pd(a,b,c,d);
        printf("%.2f\n",s);
    }
    return 0;
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值