程序员面试金典 16.13

Bisect Squares:给定两个正方形和一个二维平面,求一条平分两个正方形的最长线段,如果有多条线段,返回斜率最大的一条的两端点。

这条线段肯定过这两个正方形的中心,根据这两个中心确定一条直线,然后求4个交点,选择最远的两个就好了。

注意斜率为无穷大的问题,以及交点的求法。如果斜率在[-1, 1]之间,则交于正方形左右两边,如果斜率在[-∞, -1] ∪ [1, +∞],则交于正方形上下两边。

class Solution {
    const double EPS = 1e-6;
    struct Point
    {
        double x, y;
        Point(const vector<int> &square)
        {
            x = square[0] + square[2] / 2.0;
            y = square[1] + square[2] / 2.0;
        }
        Point(const double &x, const double &y) : x(x), y(y){}
    };
    bool equal(const double &d1, const double &d2)
    {
        return abs(d1 - d2) <= EPS;
    }
    Point extend(const Point &mid, const Point &other, const double &dir, const double &size)
    {
        double half = size / 2.0;
        if(equal(mid.x, other.x)){
            return Point(mid.x, mid.y + dir * half);
        }
        else{
            double slope = (other.y - mid.y) / (other.x - mid.x);
            if(abs(slope) < 1.0){
                return Point(mid.x + dir * half, mid.y + dir * half * slope);
            }
            else{
                return Point(mid.x + dir * half / slope, mid.y + dir * half);
            }
        }
    }
public:
    vector<double> cutSquares(vector<int>& square1, vector<int>& square2) {
        Point mid1(square1), mid2(square2);
        Point p11 = extend(mid1, mid2, -1.0, (double)square1[2]);
        Point p12 = extend(mid1, mid2, 1.0, (double)square1[2]);
        Point p21 = extend(mid2, mid1, -1.0, (double)square2[2]);
        Point p22 = extend(mid2, mid1, 1.0, (double)square2[2]);
        Point start = p11, end = p11;
        const vector<Point> vecPoints = {p12, p21, p22};
        for(size_t i = 0; i < vecPoints.size(); i++)
        {
            if(vecPoints[i].x < start.x || (equal(vecPoints[i].x, start.x) && vecPoints[i].y < start.y)){
                start = vecPoints[i];
            }
            else if(vecPoints[i].x > end.x || (equal(vecPoints[i].x, end.x) && vecPoints[i].y > end.y)){
                end = vecPoints[i];
            }
        }
        return {start.x, start.y, end.x, end.y};
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值