【题目大意】:给出你T个case。每个case有n个点,叫你求这个点的半径和圆心坐标,使得这个圆覆盖所有的点(n<=100000)
【解题思路】:曾经在zoj上做过一道最小圆的覆盖,但是那道题的点只有100,当初是暴力做的。显然碰到这个数据量是行不通的,我们可以采取dfs进行增量,或者利用随机重排进行增量,二者在spoj上测试的时间差距不大,网络模版testing。
【代码】:
dfs实现增量
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
using namespace std;
#define eps 1e-8
#define pi acos(-1.0)
#define inf 1<<30
#define linf 1LL<<60
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long
int n;
struct Point{
double x;
double y;
}pt[1005];
struct Traingle{
struct Point p[3];
};
struct Circle{
struct Point center;
double r;
}ans;
//计算两点距离
double Dis(struct Point p, struct Point q){
double dx=p.x-q.x;
double dy=p.y-q.y;
return sqrt(dx*dx+dy*dy);
}
//计算三角形面积
double Area(struct Traingle ct){
return fabs((ct.p[1].x-ct.p[0].x)*(ct.p[2].y-ct.p[0].y)-(ct.p[2].x-ct.p[0].x)*(ct.p[1].y-ct.p[0].y))/2.0;
}
//求三角形的外接圆,返回圆心和半径(存在结构体"圆"中)
struct Circle CircumCircle(struct Traingle t){
struct Circle tmp;
double a,b,c,c1,c2;
double xA,yA,xB,yB,xC,yC;
a=Dis(t.p[0],t.p[1]);
b=Dis(t.p[1],t.p[2]);
c=Dis(t.p[2],t.p[0]);
//根据S = a * b * c / R / 4;求半径R
tmp.r=(a*b*c)/(Area(t)*4.0);
xA=t.p[0].x;
yA=t.p[0].y;
xB=t.p[1].x;
yB=t.p[1].y;
xC=t.p[2].x;
yC=t.p[2].y;
c1=(xA*xA+yA*yA-xB*xB-yB*yB)/2;
c2=(xA*xA+yA*yA-xC*xC-yC*yC)/2;
tmp.center.x=(c1*(yA-yC)-c2*(yA-yB))/((xA-xB)*(yA-yC)-(xA-xC)*(yA-yB));
tmp.center.y=(c1*(xA-xC)-c2*(xA-xB))/((yA-yB)*(xA-xC)-(yA-yC)*(xA-xB));
return tmp;
}
//确定最小包围圆
struct Circle MinCircle(int num, struct Traingle ct){
struct Circle ret;
if (num==0) ret.r=0.0;
else if (num==1){
ret.center=ct.p[0];
ret.r = 0.0;
}
else if (num==2){
ret.center.x=(ct.p[0].x+ct.p[1].x)/2.0;
ret.center.y=(ct.p[0].y+ct.p[1].y)/2.0;
ret.r=Dis(ct.p[0], ct.p[1])/2.0;
}
else if(num==3) ret=CircumCircle(ct);
return ret;
}
//递归实现增量算法
void Dfs(int x, int num, struct Traingle ct){
int i, j;
struct Point tmp;
ans = MinCircle(num, ct);
if (num==3) return;
for (i=1; i<=x; i++)
if (Dis(pt[i],ans.center)>ans.r){
ct.p[num]=pt[i];
Dfs(i-1,num+1,ct);
tmp=pt[i];
for (j=i; j>=2; j--)
pt[j]=pt[j-1];
pt[1]=tmp;
}
}
void Solve(int n){
struct Traingle ct;
Dfs(n,0,ct);
}
int main(){
int T;
cin >> T;
while (T--){
scanf("%d",&n);
if (n==0) break;
for (int i=1; i<=n; i++)
scanf("%lf %lf",&pt[i].x,&pt[i].y);
Solve(n);
printf("%.2f\n",ans.r);
printf("%.2f %.2f\n",ans.center.x,ans.center.y);
}
return 0;
}
随机重排增量
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
using namespace std;
#define eps 1e-10
#define pi acos(-1.0)
#define inf 1<<30
#define linf 1LL<<60
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long
const int N=100010;
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() {
scanf("%d",&n);
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("%.2f\n%.2f %.2f\n",r,c.x,c.y);
}
int main() {
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}