一.概念引入

        最小包围圆问题:对于给定的平面上甩个点所组成的一个集合P,求出P的最小包围圆,即包含P中所有点、半径最小的那个圆。也就是求出这个最小
包围圆的圆心位置和半径。

        下面是若干性质。

  • 有限点集P的最小包围圆是唯一的。这里约定,若P中只有一个点v,则最小包围圆是退化的,其半径为0,圆心为点v。
  • 非退化最小包围圆可以由2个或者3个边界点定义。边界上只有两个点,则必定是直径两端,其它点都在圆内部,这个咱就不证明了。
  • 点集P中,距离最大的2个点A、B不一定都在边界上,但是必有d≥|AB|,笔者认为这点很重要。

  • 直角三角形或钝角三角形的3个顶点的最小包围圆是以最长边为直径的圆;锐角三角形3个顶点的最小包围圆是三角形的外接圆。
  • 新加入点一定在圆上

二.算法实现

           加上shuffle后,ZOJ1450第二组数据结果不稳定,不加的话全部正确,不过两者都还是WA,莫非求圆心也没错(水平竖直斜向都可以求出),别人的C++的都AC(用了random_shuffle()函数了,原来判断点在圆心内写错了,网上找不到java代码,不管了……

package a;
import java.util.Random;
import java.util.Scanner; /*
* hdu只有500点,可以直接两点间最大距离暴力试试
*/
public class HDU3007 { public static void main(String[] args) {
new RIA().go();
}
} class Point {
double x;
double y; public Point() {
this.x = 0;
this.y = 0;
}
} class Line {
Point a;
Point b; public Line() {
this.a = new Point();
this.b = new Point();
}
public Line(Point a,Point b) {
this.a = a;
this.b = b;
} //求两直线的交点,斜率相同的话res=u.a
Point intersection(Line u,Line v){
Point res = u.a;
double t = ((u.a.x-v.a.x)*(v.b.y-v.a.y)-(u.a.y-v.a.y)*(v.b.x-v.a.x))
/((u.a.x-u.b.x)*(v.b.y-v.a.y)-(u.a.y-u.b.y)*(v.b.x-v.a.x));
res.x += (u.b.x-u.a.x)*t;
res.y += (u.b.y-u.a.y)*t;
return res;
} //三角形外接圆圆心(外心)
// Point center(Point a,Point b,Point c) {
// //加上这个才没有编译器提示未初始化,因为new所以也写了构造方法
// Line u = new Line(),v = new Line();
// u.a.x=(a.x+b.x)/2;
// u.a.y=(a.y+b.y)/2;
// u.b.x=u.a.x+(u.a.y-a.y);
// u.b.y=u.a.y-(u.a.x-a.x);
// v.a.x=(a.x+c.x)/2;
// v.a.y=(a.y+c.y)/2;
// v.b.x=v.a.x+(v.a.y-a.y);
// v.b.y=v.a.y-(v.a.x-a.x);
// return intersection(u,v);
// }
Point center(Point a,Point b,Point c) {
Point ret = new Point();
double a1=b.x-a.x, b1=b.y-a.y, c1=(a1*a1+b1*b1)/2;
double a2=c.x-a.x, b2=c.y-a.y, c2=(a2*a2+b2*b2)/2;
double d = a1*b2 - a2*b1;
ret.x = a.x + (c1*b2-c2*b1)/d;
ret.y = a.y + (a1*c2-a2*c1)/d;
return ret;
}
} class RIA {
int n;
double x;
double y; public void go() {
Scanner sc = new Scanner(System.in);
while(true) {
n = sc.nextInt();
if(0==n)
break;
Point point[] = new Point[n];
for(int i=0; i<n; i++) {//不加的话空指针异常
point[i] = new Point();
}
for(int i=0; i<n; i++) {
x = sc.nextDouble();
y = sc.nextDouble();
point[i].x = x;
point[i].y = y;
}
//shuffle(point);
solve(point);
}
} private void shuffle(Point[] point) { for(int i=0; i<point.length; i++) {
//Random r = new Random();
//int j = r.nextInt(point.length);
int j = (int)(Math.random()*point.length);
if(i!=j) {
Point temp = point[i];
point[i] = point[j];
point[j] = temp;
}
}
} private void solve(Point[] point) { Point circle = point[0];
double r = 0; for(int i=1; i<n; i++) {
double dis = distance(circle, point[i]);
if(Double.compare(dis, r)<=0) {
continue;
}
circle = point[i];
r = 0;
for(int j=0; j<i; j++) {
dis = distance(circle, point[j]);
if(Double.compare(dis, r)<=0) {
continue;
}
circle.x = (point[j].x + point[i].x)/2;
circle.y = (point[j].y + point[i].y)/2;
r = distance(circle, point[j]); for(int k=0; k<j; k++) {
dis = distance(circle, point[k]);
if(Double.compare(dis, r)<=0) {
continue;
}
Line line = new Line();
circle = line.center(point[i],point[j],point[k]);
r = distance(point[k], circle);
} } }
//没有lf只说
System.out.println(String.format("%.2f", circle.x) +
" "+String.format("%.2f", circle.y)+
" "+String.format("%.2f", r));
//这样不行,若是初试不足三位,那么输出就不够三位
// System.out.println((double)Math.round(circle.x*100)/100 +
// " "+(double)Math.round(circle.y*100)/100+
// " "+(double)Math.round(r*100)/100); } public double distance(Point p1, Point p2) {
return (Math.hypot((p1.x - p2.x), (p1.y - p2.y)));
}
}

三.若干思考

        RIA算法叫随机增量法,加入随机性后复杂度是线性的(表示目前不太理解),昨晚又想了想,第一层循环是产生新加入的点,由性质知该点必须在圆上,所以三层循环里每层都有point[i]去组成圆(第一层中是退化的);

        第一层中为什么半径是0呢?和圆心是point[i]一样,笔者认为主要是为让第二层一定进行下去(略过if判断),或者就认为此时只有一个点是退化圆。

        如何保证最小?因为每次都是最小的(看倒数第二条性质),所以结果是最小的。

四.浮点数

        Double.compare(p,q),若是和0比,下面也可以:

double exp = 1e-10;
if (Math.abs(val1 - val2)>-1*exp && Math.abs(val1 - val2)<exp) {
//do things
}

RIA算法解决最小覆盖圆问题的更多相关文章

  1. GiftWrapping算法解决二维凸包问题

    一.问题描述 凸集(Convex Set): 任意两点的连线都在这个集合内的集合就是一个凸集.             ⒈对于一个集合D,D中任意有限个点的线性组合的全体称为D的凸包.         ...

  2. 题目1437:To Fill or Not to Fill:贪心算法解决加油站选择问题(未解决)

    //贪心算法解决加油站选择问题 //# include<iostream> # include<stdio.h> using namespace std; # include& ...

  3. xsank的快餐 » Python simhash算法解决字符串相似问题

    xsank的快餐 » Python simhash算法解决字符串相似问题 Python simhash算法解决字符串相似问题

  4. 详解zkw算法解决最小费用流问题

    网络流的一些基本概念 很多同学建立过网络流模型做题目, 也学过了各种算法, 但是对于基本的概念反而说不清楚. 虽然不同的模型在具体叫法上可能不相同, 但是不同叫法对应的思想是一致的. 下面的讨论力求规 ...

  5. SA:利用SA算法解决TSP(数据是14个虚拟城市的横纵坐标)问题——Jason niu

    %SA:利用SA算法解决TSP(数据是14个虚拟城市的横纵坐标)问题——Jason niu X = [16.4700 96.1000 16.4700 94.4400 20.0900 92.5400 2 ...

  6. Hash算法解决冲突的方法

    https://blog.csdn.net/feinik/article/details/54974293 Hash算法解决冲突的方法一般有以下几种常用的解决方法1, 开放定址法:所谓的开放定址法就是 ...

  7. hdu1533 Going Home km算法解决最小权完美匹配

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  8. 【智能算法】用模拟退火(SA, Simulated Annealing)算法解决旅行商问题 (TSP, Traveling Salesman Problem)

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 文章声明 此文章部分资料和代码整合自网上,来源太多已经无法查明出处,如侵犯您的权利,请联系我删除. 01 什么是旅行商问题(TS ...

  9. 如何理解C4.5算法解决了ID3算法的偏向于选择取值较多的特征问题

    如何理解C4.5算法解决了ID3算法的偏向于选择取值较多的特征问题 考虑一个极端情况,某个属性(特征)的取值很多,以至于每一个取值对应的类别只有一个.这样根据\[H(D) - H(D|A)\]可以得知 ...

随机推荐

  1. PL/SQL — 变长数组

    PL/SQL变长数组是PL/SQL集合数据类型中的一种,其使用方法与PL/SQL嵌套表大同小异,唯一的区别则是变长数组的元素的最大个数是有限制的.也即是说变长数组的下标固定下限等于1,上限可以扩展.下 ...

  2. Java 中正确使用 hashCode 和 equals 方法

    在这篇文章中,我将告诉大家我对hashCode和equals方法的理解.我将讨论他们的默认实现,以及如何正确的重写他们.我也将使用Apache Commons提供的工具包做一个实现. 目录: hash ...

  3. DB天气app冲刺第五天

    今天上了软工的一节课,感觉自己前几天的方向错了,而且基本是在耗时间,因为虽然一直在努力的看书 编代码,但效果不明显.所以今天要好好想一个新的方向重新来过. 明天送上计划.

  4. 客户端动态调用cxf websevice 异常

    三月 30, 2014 10:06:40 上午 org.apache.cxf.common.jaxb.JAXBUtils logGeneratedClassNames 信息: Created clas ...

  5. 《暗黑世界GM管理后台系统》部署+功能说明

    原地址:http://blog.csdn.net/uxqclm/article/details/11969761 欢迎来到9秒:www.9miao.com 暗黑三国管理后台说明文档 (一)功能描述该后 ...

  6. 服务器监控之 ping 监控

    在运维人员的日常工作中,对物理服务器的监控十分重要.物理机的 CPU.内存.磁盘使用率,网卡流量,磁盘 IO 等都需要进行监控.通过 ICMP 协议的 ping 监控,可以判断物理服务器运行是否正常或 ...

  7. TC SRM 607 DIV2

    求拼接完成后的字符串包含的子回文串的数目,一开始还用暴力去做,想都不用想 肯定超时了. 复习了一下求最长子回文串的算法,发现可以类似解决. 给相邻字符之间添加一个'@'字符,这样所有的回文串都是奇数长 ...

  8. Visual Studio 创建代码注释默认模版方法

    在日常的开发中我们经常需要为页面添加注释和版权等信息,这样我们就需要每次去拷贝粘贴同样的文字,为了减少这种重复性的工作,我们可以把这些信息保存在Visual Studio 2012类库模版文件里 1. ...

  9. 快速排序法QuickSort

    /** * * @author Administrator * 功能:交换式排序之快速排序 */ package com.test1; import java.util.Calendar; publi ...

  10. SQL server数据类型int、bigint、smallint、tinyint

    1. 整数类型 int.bigint.smallint.tinyint 数据类型 范围 存储 bigint -2^63 (-9,223,372,036,854,775,808) 到 2^63-1 (9 ...