[算法刷题题解笔记] POJ 1106 Transmitters [计算几何|叉积|点线关系]

简介: [算法刷题题解笔记] POJ 1106 Transmitters [计算几何|叉积|点线关系]

题目链接

题目大意

  • 输入第一行给出一个圆的圆心坐标及半径,再给出n个点,要求在这个圆中取出一个半圆,使这个半圆覆盖点数最多,输出这个最大点数

示例输入

  • 第一行:圆的圆心坐标和圆的半径
  • 第二行:点的个数 n
  • 第二行后面的n行:每个点的坐标
  • 输入的测试数据有若干组,输入的测试数据的结束标志,输入一个圆的圆心坐标,半径为负数
25 25 3.5
7
25 28
23 27
27 27
24 23
26 23
24 29
26 29
350 200 2.0
5
350 202
350 199
350 198
348 200
352 200
995 995 10.0
4
1000 1000
999 998
990 992
1000 999
100 100 -2.5

示例输出

3
4
4

解题思路

  • 对每组测试数据的n个点,只需保留在圆内的点即可,因为不在圆内的点不可能在半圆内,排除无效的点避免无效判断
  • 由于我们不可能枚举半圆所有的角度,因为半圆所有的角度无限多个,即半圆的放法是有无限多种的,因此我们应该考虑哪些半圆的放法是有用的。
  • 其实我们只需要枚举半圆的直径和圆内的任一点重合的情况即可,即枚举圆内的任一点在半圆的直径上的所有可能得情况下,半圆的放法,因为最优的半圆一定刚好卡上一个点,这样就才可以留充足的空间给别的点,使得半圆内的点个数最大
  • 所以我们只需暴力枚举边界(圆内的任一点在直径上),然后用叉积统计一遍在此种放置下,半圆内的点的个数,最后从所有可能的情况中取最大值即可
  • 在计算时,直径向量采取圆心指向圆内在直径上的点的表示方式,半圆在直径的左边
  • 因此,和半径向量的叉积大于等于0(逆时针方向),在半圆内;否则不在半圆内(顺时针方向)

解题代码

#include <iostream>
using namespace std;
int main() {
  // 圆心和半径 
  double circle_x, circle_y, r;
  // 还有测试数据就继续 
  while (cin >> circle_x >> circle_y >> r) {
    if (r < 0) break; // 半径为负数,退出
    int n = 0; // 点的个数 
    cin >> n;
    // 存储在圆内的点 
        // 不知道为什么数组大小写n,动态创建数组,在POJ会报编译异常
    // double xi[n];
    // double yi[n];
        // 所以数组大小直接用字面量了
        double xi[100000];
        double yi[100000];
    int cnt = 0;
    for (int i=0; i<n; i++) {
      // 输入的每个点的坐标 
      double x, y;
      cin >> x >> y;
      // 只保存在圆内的点 
      if ( ((x - circle_x) * (x - circle_x) + (y - circle_y) * (y - circle_y)) <= r * r ) {
        xi[cnt] = x;
        yi[cnt] = y;
        cnt++;
      }
    }
    // 保存答案
    int ans = 0; // 在半圆内的点的最大个数 
    // 以在圆内的每个点为边界进行判断
    // 即直径在当前枚举的点的位置上 
    for (int i=0; i<cnt; i++) {
      double x = xi[i];
      double y = yi[i];
      // 直径向量
      double diameter_x = x - circle_x;
      double diameter_y = y - circle_y; 
      // 记录当前情况下的最大值
      int max_now = 0; 
      // 判断每个点是否在当前枚举的半圆内 
      for (int j=0; j<cnt; j++) {
        // 当前要判断是否在半圆内的点和圆心组成的向量 
        double vector_x = xi[j] - circle_x;
        double vector_y = yi[j] - circle_y; 
        // 通过叉积判断是否在半圆内 
        if ((vector_x * diameter_y) - (vector_y * diameter_x) >= 0) {
          max_now++;
        } 
      } 
      // 和另外半边圆的个数比较,取较大值 
      max_now = max_now > (cnt - max_now) ? max_now : (cnt - max_now);
            // 更新答案
      ans = ans < max_now ? max_now : ans;
    }
    cout << ans << endl; 
  }
}
  • 不知道为什么数组大小写n,动态创建数组,在POJ会报编译异常,所以数组大小直接用字面量了
相关文章
|
1月前
|
算法
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
65 1
|
1月前
|
算法 索引
❤️算法笔记❤️-(每日一刷-141、环形链表)
❤️算法笔记❤️-(每日一刷-141、环形链表)
46 0
|
1月前
|
算法
【❤️算法笔记❤️】-(每日一刷-876、单链表的中点)
【❤️算法笔记❤️】-(每日一刷-876、单链表的中点)
43 0
|
1月前
|
算法 API 计算机视觉
人脸识别笔记(一):通过yuface调包(参数量54K更快更小更准的算法) 来实现人脸识别
本文介绍了YuNet系列人脸检测算法的优化和使用,包括YuNet-s和YuNet-n,以及通过yuface库和onnx在不同场景下实现人脸检测的方法。
35 1
|
1月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
59 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
1月前
|
算法
❤️算法笔记❤️-(每日一刷-160、相交链表)
❤️算法笔记❤️-(每日一刷-160、相交链表)
17 1
|
1月前
|
数据可视化 搜索推荐 Python
Leecode 刷题笔记之可视化六大排序算法:冒泡、快速、归并、插入、选择、桶排序
这篇文章是关于LeetCode刷题笔记,主要介绍了六大排序算法(冒泡、快速、归并、插入、选择、桶排序)的Python实现及其可视化过程。
14 0
|
1月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
31 0
|
1月前
|
算法
❤️算法笔记❤️-(每日一刷-26、删除有序数组的重复项)
❤️算法笔记❤️-(每日一刷-26、删除有序数组的重复项)
23 0
|
26天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。