首页 > 其他分享 >[研究中] 固定半径最少圆覆盖问题/固定数量最小半径覆盖问题

[研究中] 固定半径最少圆覆盖问题/固定数量最小半径覆盖问题

时间:2022-12-08 04:00:24浏览次数:42  
标签:覆盖 int 外接圆 枚举 圆心 固定 半径

一、固定半径最少圆覆盖问题

背景:二维坐标轴中,给出n个点以及每个点的坐标(坐标为浮点型),和一个长度m(m为浮点型),求至少需要多个半径为m的圆可以把所有点覆盖住

输入:第一行输入n和m,以下2 ~ n + 1行中第 i + 1 行 输入 x_i, y_i 表示第 i 个点的坐标

输出:一个数,表示圆的个数

其中,0 < n <= 20;-180 <= x,y <= 180

根据上表,可以支持O(2n)的算法

(整活)AI组简单粗暴算法(错误算法):

首先看看AI组给我们的代码是什么:

#include <stdio.h>
int main(){
    int n;
    float m;
    scanf("%d %f", &n, &m);
    float x[n], y[n];
    for(int i = 0; i < n; i++){
        scanf("%f %f", &x[i], &y[i]);
    }
    int count = 0;
    float cx[n], cy[n];
    for(int j = 0; j < n; j++){
        int flag = 0;
        for(int k = 0; k < count; k++){
            float distance = (x[j] - cx[k]) * (x[j] - cx[k]) + (y[j] - cy[k]) * (y[j] - cy[k]);
            if(distance <= m * m){
                flag = 1;
                break;
            }
        }
        if(flag == 0){
            cx[count] = x[j];
            cy[count] = y[j];
            count++;
        }
    }
    printf("%d", count);
    return 0;
}

时间复杂程度是O(n2),思路很简单:枚举每一个点,求每一个已经记录的圆心到该点的距离,如果在半径内则把这个点跳过;否则就将该点作为新的圆心记录。

AI的思路非常简单粗暴,但是很明显的错误点就是把每个点都作为圆心来求解,很明显这个思路是不正确的,举个例子:如果半径长m = 1,两个点(0,0),(0,2)很明显只需要一个圆心在(0,1)的圆就可以完全覆盖,但是如果用以上算法得出的结果是2,具体为什么自己可以思考一下。

这个算法也是大部分人第一时间会想到的算法,很明显是错误。

一开始我写的代码也是跟这个思路差不多,也无法完全处理两个点在圆的直径两边的情况。

思路一:暴力枚举  O(n)

首先每一个答案的圆心一定是某三个组成三角形的外接圆圆心 或者 两个点连成直线的中心。简单证明思路(并不能完全证明正确性)如下:

虽然给出了明确圆的半径m,但是并不一定所有圆的半径要去等于m,简单说就是同一个圆心中,半径为m和半径为i(i <= m)能覆盖相同数量的点,那么这个圆的半径是m和i都是一样的效果。

我们设相同圆心中,如果半径为m的圆与半径为i (i <= m) 的圆覆盖的点相同,则设这个半径为i的圆为半径m的 半径为i的等价圆 (下面可能直接称之为等价圆)。

那么我们可以推断出每一个最终答案的半径为m的圆必定存在一个半径为i的等价圆,该等价圆的弧线上至少存在两个点。为什么?因为如果一个圆能包含三个点,那么这个圆取最小半径的时候一定是这三个点连成的三角形的外接圆;如果一个圆能包含两个点,那么这个圆取最小半径时一定是以这两个点为直径;如果一个圆能包含多个点形成多个三角形的外接圆,那么这个圆半径最小的时候一定是其中三个点形成三角形的外接圆(论证自己想),假设这个外接圆半径i已经是可以枚举出的小于m的半径最大的,那么这个圆就是m的 半径为i的等价圆。

那么就可以给出暴力枚举的思路了:

  • 维护一个队列用来储存圆(圆结构体储存圆的圆心、覆盖点的个数以及覆盖点的坐标);首先枚举三个点(时间复杂程度为O(Cn2) = O(n3),求出这三个点的外接圆半径,如果半径小于等于m则加入队列;枚举两个点(时间复杂程度为O(Cn2) = O(n2)),计算这两个点的直线距离除以二,如果小于m则加入队列
  • 枚举每一个圆所覆盖的点的个数(时间复杂程度为O(n4))(此时可以维护一个并查集,如果所有的点都已经被记录则剪枝)
  • 维护一个并查集,表示点是否被连接;用Dijkstra最短路算法思想来处理最小生成树:维护一个大根堆,堆的价值为该圆的覆盖点的数量,将所有的圆塞入堆里(O(n3logn)。然后以堆是否为空做循环,取出堆首(O(1)),判断该圆的实际覆盖点的个数,也就是记录覆盖点的个数减去已经覆盖过的点个数(O(n)),如果不等于则更改覆盖点的个数重新塞入堆中(O(logn)),如果等于则进行记录并将点塞入并查集。

 综上,时间复杂程度为O(n),在n <= 20的时候完全可以1s内跑出结果

标签:覆盖,int,外接圆,枚举,圆心,固定,半径
From: https://www.cnblogs.com/zExNocs/p/16965065.html

相关文章

  • git pull 强制覆盖本地文件
    “gitpull”强制覆盖本地文件放弃本地修改,使用服务器代码覆盖本地的Git命令如下:gitfetch--allgitreset--hardorigin/mastergitpull上面代码使用master分......
  • Jmeter小技能【BeanShell断言、多个相同参数提取、固定定时器、输出执行报告】
    1、BeanShell断言比响应断言更灵活,可通过BeanShell脚本设置Faillure及FailureMessage来执行断言检查,并输出断言失败接口的响应错误内容。//获取响应结果内容Stringre......
  • jQuery实现侧边模块固定
    HTML代码:<divid="header">header</div><divid="sidebarWrap"><divid="sidebar">Sidebar</div></div><divid="main">Main</div><divid="footer">foot......
  • 从Deserialization和覆盖trustURLCodebase进行JNDI注入
    DeserializationLDAP在通过LDAP协议访问远程服务的时候,我们可以跟进到 LdapCtx#c_lookup方法中这里调用了 doSearchOnce方法获取LDAP远程返回的Result数据到最后会......
  • mysql:数据量过多时使用索引覆盖
    1.什么是索引?索引(在MySQL中也叫“键key”)是存储引擎快速找到记录的一种数据结构,通俗来说类似书本的目录,这个比方虽然被用的最多但是也是最恰如其当的,在查询书本中的......
  • element table 固定部分二级表头
    项目用vue+element开发,需求如下:表格为二级表头,一级表头下有多个二级表头,需要固定部分二级表头列在表格左侧解决思路如下:1.固定一级表头的列此时问题如下,固定一......
  • 【网络覆盖优化】基于matlab的网络覆盖遗传优化问题仿真
    建立如下的目标函数:  表示的是每一代中被选择在工作状态的节点数目。C'为对应的这些节点的覆盖范围。A为每个节点对应的覆盖范围。基于这个目标函数,我们进行仿真,获......
  • Ubuntu2204设置固定IP地址
    前言Ubuntu每次升级都会修改一部分组件.从1804开始Ubuntu开始使用netplan的方式进行网络设置.但是不同版本的配置一直在升级与变化.今天掉进坑里折腾了好久.所以这边......
  • vmware 虚拟机 设计固定ip
    vmware虚拟机设计固定ip.主要:https://cloud.tencent.com/developer/article/1538387次要:https://www.jianshu.com/p/6fdbba039d79......
  • WordPress固定链接(伪静态)的设置方法及建议设置
    WordPress是一个CMS管理系统,也就是说,WordPress的文章、页面、存档页都是通过程序从数据库里面获取数据生成的。虽然WordPress的页面可以有千千万万个,但是我们访问这......