一.概念引入

        最小包围圆问题:对于给定的平面上甩个点所组成的一个集合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. ubuntu 12.04 安装 nginx+php+mysql web服务器

    Nginx 是一个轻量级,以占用系统资源少,运行效率而成为web服务器的后起之秀,国内现在很多大型网站都以使用nginx,包括腾讯.新浪等大型信息网站,还有淘宝网站使用的是nginx二次开发的web服 ...

  2. 【Http】Http权威指南

    God Is Coder 2012-10-17 22:25 阅读:77 评论:0   <http权威指南>阅读笔记(十二) God Is Coder 2012-10-17 22:04 阅读 ...

  3. HTTP - PUT 上传文件/Shell

    今天遇到几个PUT上传的点,但是都没利用起来.一怒之下,在自己本地试了一下.步骤如下: 一.环境: 首先,根据 配置Apache服务器支持向目录PUT文件 更新一下httpd.conf文件,重启所有服 ...

  4. 使用Yeoman搭建 AngularJS 应用 (2) —— 让我们搭建一个网页应用

    原文地址:http://yeoman.io/codelab/index.html 使用Yeoman搭建简单的应用 今天将会搭建一个简单的网页程序.你将可以添加,删除,拖拽和保存. 浏览Yeoman Y ...

  5. Java之向左添加零(000001)第二种方法

    //待测试数据 int i = 100; //得到一个NumberFormat的实例 NumberFormat nf = NumberFormat.getInstance(); //设置是否使用分组 ...

  6. 【Firefly API 新版文档】Package dbentrust

    原地址:http://blog.csdn.net/uxqclm/article/details/11969653 该包下面主要是数据库的处理与memcached存储.里面封装了,从memcached数 ...

  7. POJ2221+模拟

    参考http://blog.sina.com.cn/s/blog_7de5c6210100tm1h.html 其实是水题............ #include<string.h> #i ...

  8. android 为组件添加contextMenu上下文菜单

    package com.example.fragmentNavigation2.fragment; import android.os.Bundle; import android.support.v ...

  9. UVALive - 3401 Colored Cubes

    好久没写解题回顾了.主要是没什么时间,但是还是一直在刷题,图论刷了70%的知识点,不过感觉长进不是很大,所以觉得还是得一步步来,最近还是先从刘汝佳大白书把前面基础章节刷完然后再决定以后的训练方式吧. ...

  10. 9. MonoBehaviour.StartCoroutine 开始协同程序

    function StartCoroutine (routine : IEnumerator) : Coroutine 描述:开始协同程序. 一个协同程序在执行过程中,可以在任意位置使用yield语句 ...