解题思路
我们可以将这个问题看作一个图的连通性问题,其中:
- 圆圈可以看作图中的节点。
- 如果两个圆圈相交,则它们之间有一条边连接,表示从一个圆圈到达另一个圆圈的路径。
- 使用深度优先搜索(DFS)来探索这些连通的圆圈,判断是否有路径能从矩形左上角到右下角。
具体步骤
- 初始检查:遍历所有圆圈,检查左下角 (0, 0) 和右上角 (xCorner, yCorner) 是否在任何圆圈的范围内。如果是,则路径直接被阻断,返回 false。
- 图模型与 DFS:
- 将每个相交的圆圈看作图中的节点,彼此相交的圆圈之间建立边。
- 从与左上角相交的圆圈开始,进行 DFS,检查是否能到达右下角。
- 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;
}
};