LeetCode每日一题之3235. 判断矩形的两个角落是否可达

解题思路

我们可以将这个问题看作一个图的连通性问题,其中:

  • 圆圈可以看作图中的节点。
  • 如果两个圆圈相交,则它们之间有一条边连接,表示从一个圆圈到达另一个圆圈的路径。
  • 使用深度优先搜索(DFS)来探索这些连通的圆圈,判断是否有路径能从矩形左上角到右下角。

具体步骤

  1. 初始检查:遍历所有圆圈,检查左下角 (0, 0) 和右上角 (xCorner, yCorner) 是否在任何圆圈的范围内。如果是,则路径直接被阻断,返回 false。
  2. 图模型与 DFS:
    • 将每个相交的圆圈看作图中的节点,彼此相交的圆圈之间建立边。
    • 从与左上角相交的圆圈开始,进行 DFS,检查是否能到达右下角。
  3. DFS 递归逻辑:
    • 从矩形左上角的路径开始探索,每次进入一个相邻的圆圈,检查是否可以到达右下角。
    • 如果找到路径,则返回 true,否则继续探索下一个节点。

示例代码

class Solution {
public:
    // 主函数:判断是否能找到从左下角到右上角的路径
    bool canReachCorner(int xCorner, int yCorner, vector<vector<int>>& circles) {
        vector<bool> visited(circles.size(), false);  // 记录每个圆圈是否已访问
        
        // 定义 DFS 函数,检查从第 i 个圆圈开始是否有通路到达右下角
        function<bool(int)> dfs = [&](int i) -> bool {
            int x1 = circles[i][0], y1 = circles[i][1], r1 = circles[i][2];
            // 检查当前圆是否与矩形的右下角相交
            if (circleIntersectsBottomRightOfRectangle(x1, y1, r1, xCorner, yCorner)) {
                return true;
            }
            visited[i] = true;  // 标记当前圆为已访问
            // 遍历其他圆,找到相交的圆继续 DFS
            for (int j = 0; j < circles.size(); ++j) {
                int x2 = circles[j][0], y2 = circles[j][1], r2 = circles[j][2];
                if (!visited[j] && circlesIntersectInRectangle(x1, y1, r1, x2, y2, r2, xCorner, yCorner) && dfs(j)) {
                    return true;
                }
            }
            return false;
        };

        // 初始检查:判断是否有圆覆盖了左下角或右上角
        for (int i = 0; i < circles.size(); ++i) {
            int x = circles[i][0], y = circles[i][1], r = circles[i][2];
            if (pointInCircle(0, 0, x, y, r) || pointInCircle(xCorner, yCorner, x, y, r)) {
                return false;  // 如果覆盖则无法到达
            }
            // 从与左上角相交的圆圈开始 DFS
            if (!visited[i] && circleIntersectsTopLeftOfRectangle(x, y, r, xCorner, yCorner) && dfs(i)) {
                return false;
            }
        }
        return true;  // 成功找到路径
    }

private:
    // 判断点 (px, py) 是否在圆心 (x, y)、半径为 r 的圆内
    bool pointInCircle(long long px, long long py, long long x, long long y, long long r) {
        return (x - px) * (x - px) + (y - py) * (y - py) <= (long long)r * r;
    }

    // 判断圆是否与矩形的左上角区域相交
    bool circleIntersectsTopLeftOfRectangle(int x, int y, int r, int xCorner, int yCorner) {
        return (abs(x) <= r && 0 <= y && y <= yCorner) ||           // 圆横向靠近左侧
               (0 <= x && x <= xCorner && abs(y - yCorner) <= r) || // 圆纵向靠近上侧
               pointInCircle(x, y, 0, yCorner, r);                  // 圆心靠近左上角
    }

    // 判断圆是否与矩形的右下角区域相交
    bool circleIntersectsBottomRightOfRectangle(int x, int y, int r, int xCorner, int yCorner) {
        return (abs(y) <= r && 0 <= x && x <= xCorner) ||           // 圆横向靠近底边
               (0 <= y && y <= yCorner && abs(x - xCorner) <= r) || // 圆纵向靠近右边
               pointInCircle(x, y, xCorner, 0, r);                  // 圆心靠近右下角
    }

    // 判断两个圆是否在矩形范围内相交
    bool circlesIntersectInRectangle(long long x1, long long y1, long long r1, long long x2, long long y2, long long r2, long long xCorner, long long yCorner) {
        return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) <= (r1 + r2) * (r1 + r2) &&  // 两圆相交
               x1 * r2 + x2 * r1 < (r1 + r2) * xCorner &&                                // 在矩形范围内
               y1 * r2 + y2 * r1 < (r1 + r2) * yCorner;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值