Welcome to Subscribe On Youtube

3235. Check if the Rectangle Corner Is Reachable

Description

You are given two positive integers xCorner and yCorner, and a 2D array circles, where circles[i] = [xi, yi, ri] denotes a circle with center at (xi, yi) and radius ri.

There is a rectangle in the coordinate plane with its bottom left corner at the origin and top right corner at the coordinate (xCorner, yCorner). You need to check whether there is a path from the bottom left corner to the top right corner such that the entire path lies inside the rectangle, does not touch or lie inside any circle, and touches the rectangle only at the two corners.

Return true if such a path exists, and false otherwise.

 

Example 1:

Input: xCorner = 3, yCorner = 4, circles = [[2,1,1]]

Output: true

Explanation:

The black curve shows a possible path between (0, 0) and (3, 4).

Example 2:

Input: xCorner = 3, yCorner = 3, circles = [[1,1,2]]

Output: false

Explanation:

No path exists from (0, 0) to (3, 3).

Example 3:

Input: xCorner = 3, yCorner = 3, circles = [[2,1,1],[1,2,1]]

Output: false

Explanation:

No path exists from (0, 0) to (3, 3).

Example 4:

Input: xCorner = 4, yCorner = 4, circles = [[5,5,1]]

Output: true

Explanation:

 

Constraints:

  • 3 <= xCorner, yCorner <= 109
  • 1 <= circles.length <= 1000
  • circles[i].length == 3
  • 1 <= xi, yi, ri <= 109

Solutions

Solution 1

  • class Solution {
        private int[][] circles;
        private int xCorner, yCorner;
        private boolean[] vis;
    
        public boolean canReachCorner(int xCorner, int yCorner, int[][] circles) {
            int n = circles.length;
            this.circles = circles;
            this.xCorner = xCorner;
            this.yCorner = yCorner;
            vis = new boolean[n];
            for (int i = 0; i < n; ++i) {
                var c = circles[i];
                int x = c[0], y = c[1], r = c[2];
                if (inCircle(0, 0, x, y, r) || inCircle(xCorner, yCorner, x, y, r)) {
                    return false;
                }
                if (!vis[i] && crossLeftTop(x, y, r) && dfs(i)) {
                    return false;
                }
            }
            return true;
        }
    
        private boolean inCircle(long x, long y, long cx, long cy, long r) {
            return (x - cx) * (x - cx) + (y - cy) * (y - cy) <= r * r;
        }
    
        private boolean crossLeftTop(long cx, long cy, long r) {
            boolean a = Math.abs(cx) <= r && (cy >= 0 && cy <= yCorner);
            boolean b = Math.abs(cy - yCorner) <= r && (cx >= 0 && cx <= xCorner);
            return a || b;
        }
    
        private boolean crossRightBottom(long cx, long cy, long r) {
            boolean a = Math.abs(cx - xCorner) <= r && (cy >= 0 && cy <= yCorner);
            boolean b = Math.abs(cy) <= r && (cx >= 0 && cx <= xCorner);
            return a || b;
        }
    
        private boolean dfs(int i) {
            var c = circles[i];
            long x1 = c[0], y1 = c[1], r1 = c[2];
            if (crossRightBottom(x1, y1, r1)) {
                return true;
            }
            vis[i] = true;
            for (int j = 0; j < circles.length; ++j) {
                var c2 = circles[j];
                long x2 = c2[0], y2 = c2[1], r2 = c2[2];
                if (vis[j]) {
                    continue;
                }
                if ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) > (r1 + r2) * (r1 + r2)) {
                    continue;
                }
                if (x1 * r2 + x2 * r1 < (r1 + r2) * xCorner && y1 * r2 + y2 * r1 < (r1 + r2) * yCorner
                    && dfs(j)) {
                    return true;
                }
            }
            return false;
        }
    }
    
    
  • class Solution {
    public:
        bool canReachCorner(int xCorner, int yCorner, vector<vector<int>>& circles) {
            using ll = long long;
            auto inCircle = [&](ll x, ll y, ll cx, ll cy, ll r) {
                return (x - cx) * (x - cx) + (y - cy) * (y - cy) <= r * r;
            };
            auto crossLeftTop = [&](ll cx, ll cy, ll r) {
                bool a = abs(cx) <= r && (cy >= 0 && cy <= yCorner);
                bool b = abs(cy - yCorner) <= r && (cx >= 0 && cx <= xCorner);
                return a || b;
            };
            auto crossRightBottom = [&](ll cx, ll cy, ll r) {
                bool a = abs(cx - xCorner) <= r && (cy >= 0 && cy <= yCorner);
                bool b = abs(cy) <= r && (cx >= 0 && cx <= xCorner);
                return a || b;
            };
    
            int n = circles.size();
            vector<bool> vis(n);
            auto dfs = [&](auto&& dfs, int i) -> bool {
                auto c = circles[i];
                ll x1 = c[0], y1 = c[1], r1 = c[2];
                if (crossRightBottom(x1, y1, r1)) {
                    return true;
                }
                vis[i] = true;
                for (int j = 0; j < n; ++j) {
                    if (vis[j]) {
                        continue;
                    }
                    auto c2 = circles[j];
                    ll x2 = c2[0], y2 = c2[1], r2 = c2[2];
                    if ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) > (r1 + r2) * (r1 + r2)) {
                        continue;
                    }
                    if (x1 * r2 + x2 * r1 < (r1 + r2) * xCorner && y1 * r2 + y2 * r1 < (r1 + r2) * yCorner
                        && dfs(dfs, j)) {
                        return true;
                    }
                }
                return false;
            };
    
            for (int i = 0; i < n; ++i) {
                auto c = circles[i];
                ll x = c[0], y = c[1], r = c[2];
                if (inCircle(0, 0, x, y, r) || inCircle(xCorner, yCorner, x, y, r)) {
                    return false;
                }
                if (!vis[i] && crossLeftTop(x, y, r) && dfs(dfs, i)) {
                    return false;
                }
            }
            return true;
        }
    };
    
    
  • class Solution:
        def canReachCorner(
            self, xCorner: int, yCorner: int, circles: List[List[int]]
        ) -> bool:
            def in_circle(x: int, y: int, cx: int, cy: int, r: int) -> int:
                return (x - cx) ** 2 + (y - cy) ** 2 <= r**2
    
            def cross_left_top(cx: int, cy: int, r: int) -> bool:
                a = abs(cx) <= r and 0 <= cy <= yCorner
                b = abs(cy - yCorner) <= r and 0 <= cx <= xCorner
                return a or b
    
            def cross_right_bottom(cx: int, cy: int, r: int) -> bool:
                a = abs(cx - xCorner) <= r and 0 <= cy <= yCorner
                b = abs(cy) <= r and 0 <= cx <= xCorner
                return a or b
    
            def dfs(i: int) -> bool:
                x1, y1, r1 = circles[i]
                if cross_right_bottom(x1, y1, r1):
                    return True
                vis[i] = True
                for j, (x2, y2, r2) in enumerate(circles):
                    if vis[j] or not ((x1 - x2) ** 2 + (y1 - y2) ** 2 <= (r1 + r2) ** 2):
                        continue
                    if (
                        (x1 * r2 + x2 * r1 < (r1 + r2) * xCorner)
                        and (y1 * r2 + y2 * r1 < (r1 + r2) * yCorner)
                        and dfs(j)
                    ):
                        return True
                return False
    
            vis = [False] * len(circles)
            for i, (x, y, r) in enumerate(circles):
                if in_circle(0, 0, x, y, r) or in_circle(xCorner, yCorner, x, y, r):
                    return False
                if (not vis[i]) and cross_left_top(x, y, r) and dfs(i):
                    return False
            return True
    
    
  • func canReachCorner(xCorner int, yCorner int, circles [][]int) bool {
    	inCircle := func(x, y, cx, cy, r int) bool {
    		dx, dy := x-cx, y-cy
    		return dx*dx+dy*dy <= r*r
    	}
    
    	crossLeftTop := func(cx, cy, r int) bool {
    		a := abs(cx) <= r && cy >= 0 && cy <= yCorner
    		b := abs(cy-yCorner) <= r && cx >= 0 && cx <= xCorner
    		return a || b
    	}
    
    	crossRightBottom := func(cx, cy, r int) bool {
    		a := abs(cx-xCorner) <= r && cy >= 0 && cy <= yCorner
    		b := abs(cy) <= r && cx >= 0 && cx <= xCorner
    		return a || b
    	}
    
    	vis := make([]bool, len(circles))
    
    	var dfs func(int) bool
    	dfs = func(i int) bool {
    		c := circles[i]
    		x1, y1, r1 := c[0], c[1], c[2]
    		if crossRightBottom(x1, y1, r1) {
    			return true
    		}
    		vis[i] = true
    		for j, c2 := range circles {
    			if vis[j] {
    				continue
    			}
    			x2, y2, r2 := c2[0], c2[1], c2[2]
    			if (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) > (r1+r2)*(r1+r2) {
    				continue
    			}
    			if x1*r2+x2*r1 < (r1+r2)*xCorner && y1*r2+y2*r1 < (r1+r2)*yCorner && dfs(j) {
    				return true
    			}
    		}
    		return false
    	}
    
    	for i, c := range circles {
    		x, y, r := c[0], c[1], c[2]
    		if inCircle(0, 0, x, y, r) || inCircle(xCorner, yCorner, x, y, r) {
    			return false
    		}
    		if !vis[i] && crossLeftTop(x, y, r) && dfs(i) {
    			return false
    		}
    	}
    	return true
    }
    
    func abs(x int) int {
    	if x < 0 {
    		return -x
    	}
    	return x
    }
    
    
  • function canReachCorner(xCorner: number, yCorner: number, circles: number[][]): boolean {
        const inCircle = (x: bigint, y: bigint, cx: bigint, cy: bigint, r: bigint): boolean => {
            const dx = x - cx;
            const dy = y - cy;
            return dx * dx + dy * dy <= r * r;
        };
    
        const crossLeftTop = (cx: bigint, cy: bigint, r: bigint): boolean => {
            const a = BigInt(Math.abs(Number(cx))) <= r && cy >= 0n && cy <= BigInt(yCorner);
            const b =
                BigInt(Math.abs(Number(cy - BigInt(yCorner)))) <= r &&
                cx >= 0n &&
                cx <= BigInt(xCorner);
            return a || b;
        };
    
        const crossRightBottom = (cx: bigint, cy: bigint, r: bigint): boolean => {
            const a =
                BigInt(Math.abs(Number(cx - BigInt(xCorner)))) <= r &&
                cy >= 0n &&
                cy <= BigInt(yCorner);
            const b = BigInt(Math.abs(Number(cy))) <= r && cx >= 0n && cx <= BigInt(xCorner);
            return a || b;
        };
    
        const n = circles.length;
        const vis: boolean[] = new Array(n).fill(false);
    
        const dfs = (i: number): boolean => {
            const [x1, y1, r1] = circles[i].map(BigInt);
            if (crossRightBottom(x1, y1, r1)) {
                return true;
            }
            vis[i] = true;
            for (let j = 0; j < n; j++) {
                if (vis[j]) continue;
                const [x2, y2, r2] = circles[j].map(BigInt);
                if ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) > (r1 + r2) * (r1 + r2)) {
                    continue;
                }
                if (
                    x1 * r2 + x2 * r1 < (r1 + r2) * BigInt(xCorner) &&
                    y1 * r2 + y2 * r1 < (r1 + r2) * BigInt(yCorner) &&
                    dfs(j)
                ) {
                    return true;
                }
            }
            return false;
        };
    
        for (let i = 0; i < n; i++) {
            const [x, y, r] = circles[i].map(BigInt);
            if (inCircle(0n, 0n, x, y, r) || inCircle(BigInt(xCorner), BigInt(yCorner), x, y, r)) {
                return false;
            }
            if (!vis[i] && crossLeftTop(x, y, r) && dfs(i)) {
                return false;
            }
        }
    
        return true;
    }
    
    
  • impl Solution {
        pub fn can_reach_corner(x_corner: i32, y_corner: i32, circles: Vec<Vec<i32>>) -> bool {
            let n = circles.len();
            let mut vis = vec![false; n];
    
            let in_circle = |x: i64, y: i64, cx: i64, cy: i64, r: i64| -> bool {
                (x - cx) * (x - cx) + (y - cy) * (y - cy) <= r * r
            };
    
            let cross_left_top = |cx: i64, cy: i64, r: i64| -> bool {
                let a = cx.abs() <= r && (cy >= 0 && cy <= y_corner as i64);
                let b = (cy - y_corner as i64).abs() <= r && (cx >= 0 && cx <= x_corner as i64);
                a || b
            };
    
            let cross_right_bottom = |cx: i64, cy: i64, r: i64| -> bool {
                let a = (cx - x_corner as i64).abs() <= r && (cy >= 0 && cy <= y_corner as i64);
                let b = cy.abs() <= r && (cx >= 0 && cx <= x_corner as i64);
                a || b
            };
            fn dfs(
                circles: &Vec<Vec<i32>>,
                vis: &mut Vec<bool>,
                i: usize,
                x_corner: i32,
                y_corner: i32,
                cross_right_bottom: &dyn Fn(i64, i64, i64) -> bool,
            ) -> bool {
                let c = &circles[i];
                let (x1, y1, r1) = (c[0] as i64, c[1] as i64, c[2] as i64);
    
                if cross_right_bottom(x1, y1, r1) {
                    return true;
                }
    
                vis[i] = true;
    
                for j in 0..circles.len() {
                    if vis[j] {
                        continue;
                    }
    
                    let c2 = &circles[j];
                    let (x2, y2, r2) = (c2[0] as i64, c2[1] as i64, c2[2] as i64);
    
                    if (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) > (r1 + r2) * (r1 + r2) {
                        continue;
                    }
    
                    if x1 * r2 + x2 * r1 < (r1 + r2) * x_corner as i64
                        && y1 * r2 + y2 * r1 < (r1 + r2) * y_corner as i64
                        && dfs(circles, vis, j, x_corner, y_corner, cross_right_bottom)
                    {
                        return true;
                    }
                }
                false
            }
    
            for i in 0..n {
                let c = &circles[i];
                let (x, y, r) = (c[0] as i64, c[1] as i64, c[2] as i64);
    
                if in_circle(0, 0, x, y, r) || in_circle(x_corner as i64, y_corner as i64, x, y, r) {
                    return false;
                }
    
                if !vis[i]
                    && cross_left_top(x, y, r)
                    && dfs(
                        &circles,
                        &mut vis,
                        i,
                        x_corner,
                        y_corner,
                        &cross_right_bottom,
                    )
                {
                    return false;
                }
            }
    
            true
        }
    }
    
    

All Problems

All Solutions