BNUOJ--29379 斩

一条直线分割一个矩形,求分割后面积小的那部分的面积。

http://www.bnuoj.com/bnuoj/problem_show.php?pid=29379

直线方程:ax + by + c = 0

首先特判直线平行于坐标轴的情况。。。也就是最简单的情况(虽然比赛的时候我就是折在这上面。。。QuQ

我们将剩下的情况分为红色线的情况和蓝色线的情况

红色线的情况就是直线交在矩形相邻的两条边上,即求红色区域的面积

蓝色线的情况是直线交在对边上,先求三角形的面积,在加上更小的矩形的面积

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const double  eps = 1e-5;
int t;
double xl ,yl, xr, yr, a, b, c;
bool A, B, C, D;
int main(){
    scanf("%d", &t);
    while(t--){
        scanf("%lf%lf%lf%lf%lf%lf%lf", &xl, &yl, &xr, &yr, &a, &b, &c);
        A = B = C = D = false;
        if(fabs(a) < eps){
            double y = (yl + yr) / 2.0;
            if(-c / b < y)
                printf("%.3f\n", (xr - xl) * (-c / b - yl));
            else
                printf("%.3f\n", (xr - xl) * (yr + c / b));
            continue;
        }
        if(fabs(b) < eps){
            double x = (xl +xr) / 2;
            if(-c / a < x)
                printf("%.3f\n", (yr - yl) * (-c / a - xl));
            else
                printf("%.3f\n", (yr - yl) * (xr + c / a));
            continue;
        }
        double xb = (-c / a) - (b / a) * yr;
        if((xb - xl) >= 0.0 && (xr - xb) >= 0.0) B = true;
        double xd = (-c / a) - (b / a) * yl;
        if((xd - xl) >= 0.0 && (xr - xd) >= 0.0) D = true;
        double ya = (-a / b) * xl - c / b;
        if((ya - yl) >= 0.0 && (yr - ya) >= 0.0) A = true;
        double yc = (-a / b) * xr - c / b;
        if((yc - yl) >= 0.0 && (yr - yc) >= 0.0) C = true;
        if(A && B && !C && !D){
            printf("%.3f\n", 0.5 * (yr - ya) * (xb - xl));
        }
        else if(A && D && !B && !C){
            printf("%.3f\n", 0.5 * (ya - yl) * (xd - xl));
        }
        else if(C && B && !A && !D){
            printf("%.3f\n", 0.5 * (yr - yc) * (xr - xb));
        }
        else if(C && D && !A && !B){
            printf("%.3f\n", 0.5 * (yc - yl) * (xr - xd));
        }
        else if(A && C){
            if((ya - (yl + yr) / 2.0) > eps){
                double ans = 0.5 * (xr - xl) * (ya - yc);
                if(((yr - ya) - (yc - yl)) > eps) ans += (xr - xl) * (yc - yl);
                else ans += (xr - xl) * (yr - ya);
                printf("%.3f\n", ans);
            }
            else{
                double ans = 0.5 * (xr - xl) * (yc - ya);
                if(((yr - yc) - (ya - yl)) > eps) ans += (xr - xl) * (ya - yl);
                else ans += (xr - xl) * (yr - yc);
                printf("%.3f\n", ans);
            }
        }
        else if(B && D){
            if((xb - (xr + xl) / 2.0) >eps){
                double ans = 0.5 * (yr - yl) * (xb - xd);
                if(((xr - xb) - (xd - xl)) >eps) ans += (yr - yl) * (xd - xl);
                else ans += (yr - yl) * (xr - xb);
                printf("%.3f\n", ans);
            }
            else {
                double ans = 0.5 * (yr - yl) * (xd - xb);
                if(((xr - xd) - (xb - xl)) >eps) ans += (yr - yl) * (xb - xl);
                else ans += (yr - yl) * (xr - xd);
                printf("%.3f\n", ans);
            }
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值