求助随机增量法求解最小圆覆盖
  • 板块学术版
  • 楼主cbio
  • 当前回复6
  • 已保存回复6
  • 发布时间2020/5/31 18:09
  • 上次更新2023/11/7 01:21:46
查看原帖
求助随机增量法求解最小圆覆盖
220172
cbio楼主2020/5/31 18:09

三点确定圆的方法是求两对点的连线垂直平分线再求交点
过不了样例 /kk

#include <bits/stdc++.h>
#define clear(lis) memset(lis, 0, sizeof(lis))
#define full(lis) memset(lis, 0x3f, sizeof(lis))
#define fornext(x,i) for(int i = head[x]; i; i = nxt[i])
#define mset(lis,b) memset(lis, b, sizeof(lis))
#define dbg cout<<"c "
#define Rep(i,lis,b) for(int i = (lis); i <= (b); ++i)
#define IOset(lis) freopen(lis".in", "r", stdin), freopen(lis".out", "w", stdout);
using namespace std;
typedef long long ll;
typedef double db;
const int N = 1e5 + 5;
int n, lis[N];
double x[N], y[N];
double nowx, nowy, r;//当前圆心,半径

inline double dis(int a) {		//lis[a]到圆心的距离
	return sqrt((x[lis[a]] - nowx) * (x[lis[a]] - nowx) + (y[lis[a]] - nowy) * (y[lis[a]] - nowy));
}

struct line {
	double k, b;
};

line calc(db xa, db ya, db xb, db yb) { 	//返回经过两点连线中点,垂直于两点连线的直线解析式
	db tmp = - (xb - xa) / (yb - ya);
	return (line) {tmp, (ya + yb) / 2 - (xa + xb) / 2 * tmp};
}

void reSituate(int a, int b, int c) {	//三点重新确定圆
	line la = calc(x[lis[a]], y[lis[a]], x[lis[b]], y[lis[b]]);
	line lb = calc(x[lis[b]], y[lis[b]], x[lis[c]], y[lis[c]]);
	nowx = (lb.b - la.b) / (la.k - lb.k);
	nowy = la.k * nowx + la.b;
	r = dis(a);
}


int main() {
	srand(233);
	cin >> n;
	Rep(i, 1, n) scanf("%lf%lf", &x[i], &y[i]);
	Rep(i, 1, n) lis[i] = i;
	random_shuffle(lis + 1, lis + n + 1);	//随机化
	nowx = x[lis[1]], nowy = y[lis[1]], r = 0;
	Rep(i, 2, n) {
		cout<<r<<endl;
		if (dis(i) <= r) continue;
		nowx = x[lis[i]], nowy = y[lis[i]], r = 0;
		for (int j = 1; j <= i - 1; ++j) {
			if (dis(j) <= r) continue;
			nowx = (x[lis[i]] + x[lis[j]]) / 2, nowy = (y[lis[i]] + y[lis[j]]) / 2;
			r = dis(i);
			for (int k = 1; k <= j - 1; ++k) {
				if (dis(k) <= r) continue;
				reSituate(i, j, k);
			}
		}
	}
	printf("%.2f\n%.2f %.2f\n", r, nowx, nowy);
	return 0;
}
2020/5/31 18:09
加载中...