题目:Buried memory

最小圆覆盖,很经典的问题。

题目大概是,平面上n个点,求一个半径最小的圆,能够覆盖所有的点。

如果要求一个最小覆盖圆,这个圆至少要由三个点确定。有一种算法就是任意取三个点作圆,然后判断距离圆心最远的点是否在圆

内,若在,则完成;若不在则用最远点更新这个圆。这里不仔细介绍。

这里介绍的算法是,先任意选取两个点,以这两个点的连线为直径作圆。再以此判断剩余的点,看它们是否都在圆内(或圆上),

如果都在,说明这个圆已经找到。如果没有都在:假设我们用的最开始的两个点为p[1],p[2],并且找到的第一个不在圆内(或圆

上)的点为p[i],于是我们用这个点p[i]去寻找覆盖p[1]到p[i-1]的最小覆盖圆。

那么,过确定点p[i]的从p[1]到p[i-1]的最小覆盖圆应该如何求呢?

我们先用p[1]和p[i]做圆,再从2到i-1判断是否有点不在这个圆上,如果都在,则说明已经找到覆盖1到i-1的圆。如果没有都

在:假设我们找到第一个不在这个圆上的点为p[j],于是我们用两个已知点p[j]与p[i]去找覆盖1到j-1的最小覆盖圆。

而对于两个已知点p[j]与p[i]求最小覆盖圆,只要从1到j-1中,第k个点求过p[k],p[j],p[i]三个点的圆,再判断k+1到j-1

是否都在圆上,若都在,说明找到圆;若有不在的,则再用新的点p[k]更新圆即可。

于是,这个问题就被转化为若干个子问题来求解了。

由于三个点确定一个圆,我们的过程大致上做的是从没有确定点,到有一个确定点,再到有两个确定点,再到有三个确定点来求圆的工作。

关于正确性的证明以及复杂度的计算这里就不介绍了,可以去看完整的算法介绍:恩。关于细节方面。

a.通过三个点如何求圆?

先求叉积。

若叉积为0,即三个点在同一直线,那么找到距离最远的一对点,以它们的连线为直径做圆即可;

若叉积不为0,即三个点不共线,那么就是第二个问题,如何求三角形的外接圆?

b.如何求三角形外接圆?

假设三个点(x1,y1),(x2,y2),(x3,y3);

设过(x1,y1),(x2,y2)的直线l1方程为Ax+By=C,它的中点为(midx,midy)=((x1+x2)/2,(y1+y2)/2),l1中垂线方程为A1x+B1y=C1;则它的中垂线方程中A1=-B=x2-x1,B1=A=y2-y1,C1=-B*midx+A*midy=((x2^2-x1^2)+(y2^2-y1^2))/2;

同理可以知道过(x1,y1),(x3,y3)的直线的中垂线的方程。

于是这两条中垂线的交点就是圆心。

c.如何求两条直线交点?

设两条直线为A1x+B1y=C1和A2x+B2y=C2。

设一个变量det=A1*B2-A2*B1;

如果det=0,说明两直线平行;若不等于0,则求交点:x=(B2*C1 -B1*C2)/det,y=(A1*C2-A2*C1)/det;

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>
using namespace std;
struct Point
{
double x,y;
};
Point a[1005],d;
double r;
double dist(Point A,Point B)
{
return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}
double cross(Point A,Point B,Point C)
{
return (B.x-A.x)*(C.y-A.y)-(C.x-A.x)*(B.y-A.y);
}
void MiniDiscWith2Point(Point p,Point q,int n)
{
d.x=(p.x+q.x)/2.0;
d.y=(p.y+q.y)/2.0;
r=dist(p,q)/2;
int k;
double c1,c2,t1,t2,t3;
for(k=1;k<=n;k++)
{
if(dist(d,a[k])<=r) continue;
if(cross(p,q,a[k])!=0.0)
{
c1=(p.x*p.x+p.y*p.y-q.x*q.x-q.y*q.y)/2.0;
c2=(p.x*p.x+p.y*p.y-a[k].x*a[k].x-a[k].y*a[k].y)/2.0;
d.x=(c1*(p.y-a[k].y)-c2*(p.y-q.y))/((p.x-q.x)*(p.y-a[k].y)-(p.x-a[k].x)*(p.y-q.y));
d.y=(c1*(p.x-a[k].x)-c2*(p.x-q.x))/((p.y-q.y)*(p.x-a[k].x)-(p.y-a[k].y)*(p.x-q.x));
r=dist(d,a[k]);
}
else
{
t1=dist(p,q);
t2=dist(q,a[k]);
t3=dist(p,a[k]);
if(t1>=t2&&t1>=t3)
{
d.x=(p.x+q.x)/2.0;
d.y=(p.y+q.y)/2.0;
r=dist(p,q)/2.0;
}
else if(t2>=t1&&t2>=t3)
{
d.x=(a[k].x+q.x)/2.0;
d.y=(a[k].y+q.y)/2.0;
r=dist(a[k],q)/2.0;
}
else
{
d.x=(a[k].x+p.x)/2.0;
d.y=(a[k].y+p.y)/2.0;
r=dist(a[k],p)/2.0;
}
}
}
}
void MiniDiscWithPoint(Point pi,int n)
{
d.x=(pi.x+a[1].x)/2.0;
d.y=(pi.y+a[1].y)/2.0;
r=dist(pi,a[1])/2.0;
int j;
for(j=2;j<=n;j++)
{
if(dist(d,a[j])<=r) continue;
else
{
MiniDiscWith2Point(pi,a[j],j-1);
}
}
}
int main()
{
int i,n;
while(scanf("%d",&n)&&n)
{
for(i=1;i<=n;i++)
scanf("%lf %lf",&a[i].x,&a[i].y);
if(n==1)
{
printf("%.2lf %.2lf 0.00\n",a[1].x,a[1].y);
continue;
}
r=dist(a[1],a[2])/2.0;
d.x=(a[1].x+a[2].x)/2.0;
d.y=(a[1].y+a[2].y)/2.0;
for(i=3;i<=n;i++)
{
if(dist(d,a[i])<=r)continue;
else MiniDiscWithPoint(a[i],i-1);
}
printf("%.2lf %.2lf %.2lf\n",d.x,d.y,r);
}
return 0;
}

hdu3007(最小覆盖圆问题)相关推荐

  1. 2021年度热身训练赛第一场

    2021年度热身训练赛第一场 A.Weird Flecks, But OK 题意 给定n个点以及n个点的三维坐标,用一根长度不限的圆柱以垂直x-y平面,x-z平面或y-z平面方式穿过所有点,求圆柱的最 ...

  2. matlab的fmincon函数如何传入额外参数或数据?

    文章目录 一.关于matlab的fmincon函数 二.使用匿名函数句柄传入额外参数或数据例子 一.关于matlab的fmincon函数   fmincon是matlab的带约束的非线性优化模型的求解 ...

  3. 697. Degree of an Array 频率最高元素的最小覆盖子数组

    [抄题]: Given a non-empty array of non-negative integers nums, the degree of this array is defined as ...

  4. 【FJOI2015】最小覆盖双圆问题

    题目描述 给定平面上n个点(x_1,y_1),...,(x_n,y_n)(x1​,y1​),...,(xn​,yn​),找出2个半径相同的圆R_1R1​和R_2R2​,覆盖给定的n个点,且半径最小. ...

  5. hdu 1528+hdu 1962(最小覆盖)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1528 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1 ...

  6. 二分图最小覆盖的Konig定理及其证明

    二分图: 顶点可以分类两个集合X和Y,所有的边关联在两个顶点中,恰好一个属于集合X,另一个属于集合Y. 最小覆盖: 最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联.可以证 ...

  7. Leetcode 76最小覆盖子串77组合78子集

    新人公众号(求支持):bigsai 专注于Java.数据结构与算法,一起进大厂不迷路! 算法文章题解全部收录在github仓库bigsai-algorithm,求star! 关注回复进群即可加入力扣打 ...

  8. 双指针算法之滑动窗口 | 力扣76.最小覆盖字串

    本文讲解力扣76.最小覆盖字串问题 主要用到的是滑动窗口的思想 目录 76.最小覆盖字串 题目: 分析: 步骤描述: 复杂度分析: 结果 76.最小覆盖字串 题目: 给定字符串 S 以及字符串 T , ...

  9. POJ 2069最小球覆盖 HDU3007最小圆覆盖【模拟淬火算法】

    POJ 2069最小球覆盖 1.给定N个三维点,要求覆盖这些点的最小球半径: 2.采用模拟淬火算法,随机选取一个点作为初始解,然后不断向当前最远的点靠近: 3.这是一个不断调整的过程,对应模拟淬火算法 ...

最新文章

  1. stm32f4之GPIO
  2. 2021暑假每日一题 【week9 完结】
  3. linux ubuntu 17,Ubuntu 17.04(Zesty Zapus)已经结束支持,请升级到Ubuntu 17.10
  4. android微信电话锁屏,iPhone的微信更新锁屏下呼叫提醒,终于可以直接代替电话了...
  5. jenkins 启动_CentOS 7 安装 Jenkins
  6. Revvel如何将视频转码速度提升几十倍?
  7. 15 - java 继承
  8. 什么是kubernetes_Kubernetes为什么如此受欢迎?
  9. m_Orchestrate learning system---三十一、模板和需求的关系
  10. golang实现文件服务器,【Golang】实现文件服务器断点续传
  11. 蓝桥杯 前缀判断——2013年省赛C/C++A组真题5
  12. 命令行工具解析Crash文件,dSYM文件进行符号化
  13. 商用密码产品认证-电子签章系统
  14. linux一键安装aria2,Centos7下安装Aria2教程 之 Aria2 一键安装管理脚本
  15. 自锁时间电路plc_自锁与互锁电路的plc梯形图程序【图】
  16. make VERBOSE=1等的作用
  17. ElementUI 整体页面布局
  18. 谷歌JsonObject
  19. 计算机网络三级考的是什么,三级网络技术都考什么东西?
  20. 刚子扯谈:标题木有啊

热门文章

  1. Java EE API整合:为什么Spring要与“笨重”的Java EE共舞?
  2. 使用response的outputstream
  3. 模块-开发原则以及导入文件时会执行没有缩进的代码
  4. 函数的不同的调用方式 函数也是对象 数组的函数调用 apply和call方法的使用
  5. FastDFS配置手册trackerstorage
  6. 消控中心人员配置_关于2018年度环创中心楼宇物业综合管理考评情况的通报
  7. 解决GitLab中使用SSH的git clone总是提示输入密码且任何密码都不对
  8. Linux--结构体的详细学习
  9. LinuxC-运算符
  10. static的用法及其与auto的区别小结