一.概念引入

        最小包围圆问题:对于给定的平面上甩个点所组成的一个集合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. 一步步学习NHibernate(7)——HQL查询(1)

    请注明转载地址:http://www.cnblogs.com/arhat 从本章开始,老魏带着大家来学习一下HQL语句.HQL语句NHibernate为我们提供的一种功能比较强大的查询语句,这个HQL ...

  2. 当页面编辑或运行提交时,出现“从客户端中检测到有潜在危险的request.form值”问题,该怎么办呢?

    最近在学习highcharts时,关于其中的导出功能,本来是想把导出的图片存放在本地,发现只有在电脑联网的情况下才可以一下导出图片,后来查阅了一番资料,才发现highcharts中的导出默认的官网服务 ...

  3. Spring 数据源配置一:单一数据源

    最近遇到一个项目,需要访问都多个数据源,并且数据库是不同厂商(mysql,  sqlserver). 所以对此做了一些研究,这里咱们采用渐进的方式来展开,先谈谈单一数据源配置.(稍后有时间会陆续补充其 ...

  4. js二级下拉菜单

    看似简单的一个菜单,确需要不少的知识点 1. getByClass getElementsByClassName 已经有大部分现代浏览器支持了,只有ie6,ie7,ie8是不支持的.所以对ie6,7, ...

  5. python的split用法

    Python中没有字符类型的说法,只有字符串,这里所说的字符就是只包含一个字符的字符串!!!这里这样写的原因只是为了方便理解,仅此而已. 1. 按照某一个分隔符分割一个字符串: >>> ...

  6. ExtJS 获取浏览器宽度

    JS中代码: Ext.onReady(function() { var width=window.screen.availWidth; var height=window.screen.availHe ...

  7. 当 ITOA 遇上 OneAlert,企业可以至少每年节省 3600 小时!

    每个工作日,一家大型企业都可能存在一两件优先级为 1 级的事件,五六件优先级为 2 级的事件和百来件优先级为 3 级的事件.试想一下,如果公司所有支持人员都要收到每个事件的通知--不想了,我好方!还能 ...

  8. No Pain No Game

    hdu4630:http://acm.hdu.edu.cn/showproblem.php?pid=4630 题意:给定一个排序,求区间最大GCD. 题解:离散树状数组.首先把查询按左端点从大到小排序 ...

  9. POJ 2983 Is the Information Reliable?(差分约束系统)

    http://poj.org/problem?id=2983 题意:N 个 defense stations,M条消息,消息有精确和模糊之分,若前边为P.则为精确消息,有两个defense stati ...

  10. android 在activity中改变标题栏的标题 tabActivity的标题改变

    在activity中改变标题栏的标题是调用setTitle()方法,参数为标题名称. 而tabActivity跟Activity是一样的,因此在onCheckedChanged()方法中要动态改变标题 ...