ch_g

ECUST_ACMer —— ch_g
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

[Balkan2002][Alien最小圆覆盖][随机增量法]

Posted on 2011-03-04 23:43  ch_g  阅读(702)  评论(1编辑  收藏  举报

随机增量法真是太犀利了。头一次接触随机算法,被他所折服了

ZOJ 1450 和 HDU 3007都是最小圆覆盖的题目,不过规模比起http://61.187.179.132:8080/JudgeOnline/showproblem?problem_id=1336

这个OJ上的真是小巫见大巫了。

/*
题目:Alien最小圆覆盖
题目来源:Balkan2002
http://61.187.179.132:8080/JudgeOnline/showproblem?problem_id=1336
题目难度:中等
题目内容或思路:
随机增量法 + 最小圆覆盖
做题日期:2011.3.4
*/
#include
<cstdio>
#include
<cstdlib>
#include
<climits>
#include
<iostream>
#include
<algorithm>
#include
<cstring>
#include
<string>
#include
<queue>
#include
<map>
#include
<vector>
#include
<bitset>
#include
<cmath>
#include
<set>
#include
<utility>
#include
<ctime>
using namespace std;

const int N = 100010;
const double eps = 1e-12;
int n;

struct cpoint {
double x, y;
}cp[N];

int dcmp(double x) {
if (x < -eps) return -1; else return x > eps;
}

double sqr(double x) { return x * x; }

double dis(cpoint p1, cpoint p2) {
return sqrt(sqr(p1.x - p2.x) + sqr(p1.y - p2.y));
}

void center(cpoint p0, cpoint p1, cpoint p2, cpoint &cp) { //三角形外心
double a1=p1.x-p0.x, b1=p1.y-p0.y, c1=(sqr(a1)+sqr(b1))/2;
double a2=p2.x-p0.x, b2=p2.y-p0.y, c2=(sqr(a2)+sqr(b2))/2;
double d = a1 * b2 - a2 * b1;
cp.x
= p0.x + (c1 * b2 - c2 * b1) / d;
cp.y
= p0.y + (a1 * c2 - a2 * c1) / d;
}

void MinCir(cpoint cp[], int n, cpoint &c, double &r) {
random_shuffle(cp, cp
+ n);
c
= cp[0]; r = 0;
for (int i = 1; i < n; ++i) {
if (dcmp(dis(cp[i], c) - r) <= 0) continue;
c
= cp[i]; r = 0;
for (int j = 0; j < i; ++j) {
if (dcmp(dis(cp[j], c) - r) <= 0) continue;
c.x
= (cp[i].x + cp[j].x) / 2;
c.y
= (cp[i].y + cp[j].y) / 2;
r
= dis(c, cp[j]);
for (int k = 0; k < j; ++k) {
if (dcmp(dis(cp[k], c) - r) <= 0) continue;
center(cp[i], cp[j], cp[k], c);
r
= dis(c, cp[k]);
}
}
}
}

void solve() {
for (int i = 0; i < n; ++i) {
scanf(
"%lf%lf", &cp[i].x, &cp[i].y);
}
cpoint c;
double r;
MinCir(cp, n, c, r);
printf(
"%.10lf\n%.10lf %.10lf\n", r, c.x, c.y);
}

int main() {
#ifndef ONLINE_JUDGE
freopen(
"D:\\in.txt", "r", stdin);
#endif
while (scanf("%d", &n) != EOF) {
solve();
}
return 0;
}