CSU 1812 三角形和矩形

Description

Bobo 有一个三角形和一个矩形,他想求他们交的面积。
具体地,三角形和矩形由 8 个整数 x 1,y 1,x 2,y 2,x 3,y 3,x 4,y 4 描述。 表示三角形的顶点坐标是 (x 1,y 1),(x 1,y 2),(x 2,y 1), 矩形的顶点坐标是 (x 3,y 3),(x 3,y 4),(x 4,y 4),(x 4,y 3).

Input

输入包含不超过 30000 组数据。
每组数据的第一行包含 4 个整数 x 1,y 1,x 2,y 2 (x 1≠x 2,y 1≠y 2).
第二行包含 4 个整数 x 3,y 3,x 4,y 4 (x 3<x 4,y 3<y 4).
(0≤x i,y i≤10 4)

Output

对于每组数据,输出一个实数表示交的面积。绝对误差或相对误差小于 10 -6 即认为正确。

Sample Input

1 1 3 3
0 0 2 2
0 3 3 1
0 0 2 2
4462 1420 2060 2969
4159 257 8787 2970

Sample Output

1.00000000
0.75000000

439744.13967527

几何题,求三角形和矩形的相交面积,套板子应该就可以搞定。

不过由于本题的三角形和矩形都很规矩,所以可以考虑用扫描线按照x坐标轴一条一条的扫。

不过这么做需要考虑到相交部分的各种情况,实在有些坑爹。

#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define per(i,j,k) for (int i = j; i >= k; i--)
#define loop(i,j,k) for (int i = j;i != -1; i = k[i])
#define lson x << 1, l, mid
#define rson x << 1 | 1, mid + 1, r
#define ff first
#define ss second
#define mp(i,j) make_pair(i,j)
#define pb push_back
#define pii pair<int,LL>
#define in(x) scanf("%d", &x);
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const double eps = 1e-9;
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
int T, n, m;
int x[5], y[5];
 
double get(double g)
{
    if (g < min(x[1], x[2]) || g > max(x[1], x[2])) return -INF;
    double k = 1.0*fabs(g - x[2]) / fabs(x[1] - x[2]);
    double L = y[1], R = y[1] + (y[1] < y[2] ? k : -k)*abs(y[1] - y[2]);
    if (L > R) swap(L, R);
    return max(min(1.0*y[4], R) - max(1.0*y[3], L), 0.0);
}
 
int main()
{
    while (scanf("%d%d", &x[1], &y[1]) != EOF)
    {
        rep(i, 2, 4) scanf("%d%d", &x[i], &y[i]);
        double L = get(x[3]), ans = 0;
        rep(i, x[3] + 1, x[4])
        {
            double R = get(i);
            if (L != -INF && R != -INF)
            {
                if (fabs(L + R - 2 * get(i - 0.5)) < eps) ans += (L + R) / 2;
                else
                {
                    double l = i - 1, r = i;
                    while (l + eps < r)
                    {
                        double mid = (l + r) / 2;
                        if (fabs(get(mid) - L) < eps) l = mid; else r = mid;
                    }
                    double q = i - 1, h = i;
                    while (q + eps < h)
                    {
                        double mid = (q + h) / 2;
                        if (fabs(get(mid) - R) < eps) h = mid; else q = mid;
                    }
                    ans += L*(l - i + 1) + R*(i - q) + (L + R)*(q - l) / 2;
                }
            }
            L = R;
        }
        printf("%.8lf\n", ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值