点圆关系

点圆关系

问题描述

点圆关系处理平面上点与圆之间的基本关系,包括点到圆的距离、点在圆内外的判断等。常用于范围查询和碰撞检测问题。

基本操作

算法思想

  1. 使用圆心和半径表示圆
  2. 基于距离进行判断
  3. 适用于范围和位置判断
  4. 时间复杂度

代码实现

class Circle {
public:
    Point center;
    double radius;
    
    Circle(Point c = Point(), double r = 0) : center(c), radius(r) {}
    
    // 判断点在圆内
    bool contains(const Point& p) const {
        return center.distance(p) <= radius + EPS;
    }
    
    // 判断点在圆上
    bool onCircle(const Point& p) const {
        return abs(center.distance(p) - radius) < EPS;
    }
    
    // 点到圆的最短距离
    double distanceToPoint(const Point& p) const {
        double d = center.distance(p);
        return max(0.0, d - radius);
    }
    
    // 计算圆的面积
    double area() const {
        return M_PI * radius * radius;
    }
    
    // 计算圆的周长
    double perimeter() const {
        return 2 * M_PI * radius;
    }
};
class Circle {
    Point center;
    double radius;
    static final double EPS = 1e-10;
    static final double PI = Math.PI;
    
    Circle(Point c, double r) {
        this.center = c;
        this.radius = r;
    }
    
    // 判断点在圆内
    boolean contains(Point p) {
        return center.distance(p) <= radius + EPS;
    }
    
    // 判断点在圆上
    boolean onCircle(Point p) {
        return Math.abs(center.distance(p) - radius) < EPS;
    }
    
    // 点到圆的最短距离
    double distanceToPoint(Point p) {
        double d = center.distance(p);
        return Math.max(0.0, d - radius);
    }
    
    // 计算圆的面积
    double area() {
        return PI * radius * radius;
    }
    
    // 计算圆的周长
    double perimeter() {
        return 2 * PI * radius;
    }
}
class Circle:
    def __init__(self, center: Point = Point(), radius: float = 0):
        self.center = center
        self.radius = radius
        self.EPS = 1e-10
        self.PI = math.pi
    
    # 判断点在圆内
    def contains(self, p: Point) -> bool:
        return self.center.distance(p) <= self.radius + self.EPS
    
    # 判断点在圆上
    def on_circle(self, p: Point) -> bool:
        return abs(self.center.distance(p) - self.radius) < self.EPS
    
    # 点到圆的最短距离
    def distance_to_point(self, p: Point) -> float:
        d = self.center.distance(p)
        return max(0.0, d - self.radius)
    
    # 计算圆的面积
    def area(self) -> float:
        return self.PI * self.radius * self.radius
    
    # 计算圆的周长
    def perimeter(self) -> float:
        return 2 * self.PI * self.radius

时间复杂度分析

操作 时间复杂度 空间复杂度
点在圆内判断
点在圆上判断
点到圆距离
面积周长计算

应用场景

  1. 范围查询
  2. 碰撞检测
  3. 区域判断
  4. 面积计算
  5. 几何构造

注意事项

  1. 浮点数精度
  2. 边界情况
  3. 特殊情况
  4. 坐标范围
  5. 数值稳定性

常见变形

  1. 圆与点集
class Solution {
public:
    // 找出圆内的所有点
    vector<Point> pointsInCircle(const Circle& circle, 
                               const vector<Point>& points) {
        vector<Point> result;
        for (const Point& p : points) {
            if (circle.contains(p)) {
                result.push_back(p);
            }
        }
        return result;
    }
    
    // 找出离圆最近的k个点
    vector<Point> nearestKPoints(const Circle& circle,
                               const vector<Point>& points,
                               int k) {
        vector<pair<double, Point>> distances;
        for (const Point& p : points) {
            distances.emplace_back(circle.distanceToPoint(p), p);
        }
        
        partial_sort(distances.begin(), 
                    distances.begin() + k,
                    distances.end());
        
        vector<Point> result;
        for (int i = 0; i < k && i < distances.size(); i++) {
            result.push_back(distances[i].second);
        }
        return result;
    }
};
class Solution {
    // 找出圆内的所有点
    public List<Point> pointsInCircle(Circle circle, Point[] points) {
        List<Point> result = new ArrayList<>();
        for (Point p : points) {
            if (circle.contains(p)) {
                result.add(p);
            }
        }
        return result;
    }
    
    // 找出离圆最近的k个点
    public List<Point> nearestKPoints(Circle circle, Point[] points, int k) {
        PriorityQueue<Point> pq = new PriorityQueue<>(
            (a, b) -> Double.compare(
                circle.distanceToPoint(a),
                circle.distanceToPoint(b)
            )
        );
        
        for (Point p : points) {
            pq.offer(p);
        }
        
        List<Point> result = new ArrayList<>();
        for (int i = 0; i < k && !pq.isEmpty(); i++) {
            result.add(pq.poll());
        }
        return result;
    }
}
class Solution:
    # 找出圆内的所有点
    def points_in_circle(self, circle: Circle, 
                        points: List[Point]) -> List[Point]:
        return [p for p in points if circle.contains(p)]
    
    # 找出离圆最近的k个点
    def nearest_k_points(self, circle: Circle,
                        points: List[Point], k: int) -> List[Point]:
        return sorted(points,
                     key=lambda p: circle.distance_to_point(p))[:k]
  1. 最小圆覆盖
class Solution {
public:
    // 计算包含所有点的最小圆
    Circle minCircleCover(vector<Point>& points) {
        if (points.empty()) return Circle();
        if (points.size() == 1) return Circle(points[0], 0);
        
        // 随机打乱点的顺序
        random_shuffle(points.begin(), points.end());
        
        Circle circle(points[0], 0);
        for (int i = 1; i < points.size(); i++) {
            if (!circle.contains(points[i])) {
                circle = Circle(points[i], 0);
                for (int j = 0; j < i; j++) {
                    if (!circle.contains(points[j])) {
                        circle = makeCircleFromTwo(points[i], points[j]);
                        for (int k = 0; k < j; k++) {
                            if (!circle.contains(points[k])) {
                                circle = makeCircleFromThree(
                                    points[i], points[j], points[k]
                                );
                            }
                        }
                    }
                }
            }
        }
        return circle;
    }

private:
    Circle makeCircleFromTwo(const Point& p1, const Point& p2) {
        Point center((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
        return Circle(center, center.distance(p1));
    }
    
    Circle makeCircleFromThree(const Point& p1, const Point& p2, 
                             const Point& p3) {
        // 三点确定一个圆
        double a = p2.x - p1.x, b = p2.y - p1.y,
               c = p3.x - p1.x, d = p3.y - p1.y;
        double e = a * (p1.x + p2.x) + b * (p1.y + p2.y);
        double f = c * (p1.x + p3.x) + d * (p1.y + p3.y);
        double g = 2 * (a * (p3.y - p2.y) - b * (p3.x - p2.x));
        
        if (abs(g) < EPS) return Circle();
        
        Point center(
            (d * e - b * f) / g,
            (a * f - c * e) / g
        );
        return Circle(center, center.distance(p1));
    }
};
class Solution {
    // 计算包含所有点的最小圆
    public Circle minCircleCover(Point[] points) {
        if (points.length == 0) return new Circle(new Point(), 0);
        if (points.length == 1) return new Circle(points[0], 0);
        
        // 随机打乱点的顺序
        List<Point> list = Arrays.asList(points);
        Collections.shuffle(list);
        points = list.toArray(new Point[0]);
        
        Circle circle = new Circle(points[0], 0);
        for (int i = 1; i < points.length; i++) {
            if (!circle.contains(points[i])) {
                circle = new Circle(points[i], 0);
                for (int j = 0; j < i; j++) {
                    if (!circle.contains(points[j])) {
                        circle = makeCircleFromTwo(points[i], points[j]);
                        for (int k = 0; k < j; k++) {
                            if (!circle.contains(points[k])) {
                                circle = makeCircleFromThree(
                                    points[i], points[j], points[k]
                                );
                            }
                        }
                    }
                }
            }
        }
        return circle;
    }
    
    private Circle makeCircleFromTwo(Point p1, Point p2) {
        Point center = new Point(
            (p1.x + p2.x) / 2,
            (p1.y + p2.y) / 2
        );
        return new Circle(center, center.distance(p1));
    }
    
    private Circle makeCircleFromThree(Point p1, Point p2, Point p3) {
        // 三点确定一个圆
        double a = p2.x - p1.x, b = p2.y - p1.y,
               c = p3.x - p1.x, d = p3.y - p1.y;
        double e = a * (p1.x + p2.x) + b * (p1.y + p2.y);
        double f = c * (p1.x + p3.x) + d * (p1.y + p3.y);
        double g = 2 * (a * (p3.y - p2.y) - b * (p3.x - p2.x));
        
        if (Math.abs(g) < EPS) return new Circle(new Point(), 0);
        
        Point center = new Point(
            (d * e - b * f) / g,
            (a * f - c * e) / g
        );
        return new Circle(center, center.distance(p1));
    }
}
class Solution:
    # 计算包含所有点的最小圆
    def min_circle_cover(self, points: List[Point]) -> Circle:
        if not points:
            return Circle()
        if len(points) == 1:
            return Circle(points[0], 0)
        
        # 随机打乱点的顺序
        random.shuffle(points)
        
        circle = Circle(points[0], 0)
        for i in range(1, len(points)):
            if not circle.contains(points[i]):
                circle = Circle(points[i], 0)
                for j in range(i):
                    if not circle.contains(points[j]):
                        circle = self.make_circle_from_two(
                            points[i], points[j]
                        )
                        for k in range(j):
                            if not circle.contains(points[k]):
                                circle = self.make_circle_from_three(
                                    points[i], points[j], points[k]
                                )
        return circle
    
    def make_circle_from_two(self, p1: Point, p2: Point) -> Circle:
        center = Point(
            (p1.x + p2.x) / 2,
            (p1.y + p2.y) / 2
        )
        return Circle(center, center.distance(p1))
    
    def make_circle_from_three(self, p1: Point, p2: Point, 
                             p3: Point) -> Circle:
        # 三点确定一个圆
        a = p2.x - p1.x
        b = p2.y - p1.y
        c = p3.x - p1.x
        d = p3.y - p1.y
        e = a * (p1.x + p2.x) + b * (p1.y + p2.y)
        f = c * (p1.x + p3.x) + d * (p1.y + p3.y)
        g = 2 * (a * (p3.y - p2.y) - b * (p3.x - p2.x))
        
        if abs(g) < self.EPS:
            return Circle()
        
        center = Point(
            (d * e - b * f) / g,
            (a * f - c * e) / g
        )
        return Circle(center, center.distance(p1))
牛客代码笔记-牛栋 文章被收录于专栏

汗牛充栋,学海无涯。<br/> 内含算法知识点讲解,以及牛客题库精选例题。<br/> 学习算法,从牛栋开始。

全部评论

相关推荐

真tmd的恶心,1.面试开始先说我讲简历讲得不好,要怎样讲怎样讲,先讲背景,再讲技术,然后再讲提升多少多少,一顿说教。2.接着讲项目,我先把背景讲完,开始讲重点,面试官立即打断说讲一下重点,无语。3.接着聊到了项目的对比学习的正样本采样,说我正样本采样是错的,我解释了十几分钟,还是说我错的,我在上一家实习用这个方法能work,并经过市场的检验,并且是顶会论文的复现,再怎么不对也不可能是错的。4.面试官,说都没说面试结束就退出会议,把面试者晾在会议里面,丝毫不尊重面试者难受的点:1.一开始是讲得不好是欣然接受的,毕竟是学习。2.我按照面试官的要求,先讲背景,再讲技术。当我讲完背景再讲技术的时候(甚至已经开始蹦出了几个技术名词),凭什么打断我说讲重点,是不能听出人家重点开始了?这也能理解,每个人都有犯错,我也没放心上。3.我自己做过的项目,我了解得肯定比他多,他这样贬低我做过的项目,说我的工作是错误的,作为一个技术人员,我是完全不能接受的,因此我就和他解释,但无论怎么解释都说我错。凭什么,作为面试官自己不了解相关技术,别人用这个方式work,凭什么还认为这个方法是错的,不接受面试者的解释。4.这个无可厚非,作为面试官,不打招呼就退出会议,把面试者晾着,本身就是有问题。综上所述,我现在不觉得第一第二点也是我的问题,面试官有很大的问题,就是专门恶心人的,总结面试官说教,不尊重面试者,打击面试者,不接受好的面试者,技术一般的守旧固执分子。有这种人部门有这种人怎么发展啊。最后去查了一下,岗位关闭了。也有可能是招到人了来恶心人的,但是也很cs
牛客20646354...:招黑奴啊,算法工程师一天200?
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务