WARNING: this is not the AC solution. it got TLE on the online judge!!!
有最小圓覆蓋的模板~
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <iomanip> #include <cstdlib> using namespace std; typedef long double ld; const ld eps = 1e-9; struct P { ld x,y; P(){} P(ld _x,ld _y) : x(_x),y(_y){} void scan() { cin >> x >> y; } }; P operator+(const P &p1,const P &p2) { return P(p1.x+p2.x,p1.y+p2.y); } P operator-(const P &p1,const P &p2) { return P(p1.x-p2.x,p1.y-p2.y); } P operator*(const ld &d,const P &p1) { return P(p1.x*d,p1.y*d); } P operator*(const P &p1,const ld &d) { return P(p1.x*d,p1.y*d); } ld dot(const P &p1,const P &p2) { return p1.x*p2.x + p1.y*p2.y; } ld cross(const P &p1,const P &p2) { return p1.x*p2.y - p1.y*p2.x; } ld dis(const P &p1,const P &p2) { return sqrt(dot(p1-p2,p1-p2)); } P Rotate(P p) { return P(-p.y,p.x); } struct Line { P x,v; //point x which has vector v Line() {} Line(P _x,P _v) : x(_x),v(_v){} }; P inter(const Line &l1,const Line &l2) { P p1=l1.x,p2=l1.x+l1.v; P q1=l2.x,q2=l2.x+l2.v; return p1 + (p2-p1)*(cross(q2-q1,p1-q1)/cross(p2-p1,q2-q1)); } struct Circle { P p; ld r; Circle() : p(P()),r(0) {} Circle(P _p,ld _r) : p(_p),r(_r) {} }; bool in_cir(Circle c,P p) { return dis(c.p,p) < c.r + eps; } const int N = 100006; P p[N]; P a[N]; int n,m; Circle min_cir_cover(int L,int R) { int n=R-L+1; for (int i=1;n>=i;++i) { a[i] = p[L+i-1]; } random_shuffle(a+1,a+n+1); Circle ans = Circle(P(0,0),0); for (int i=1;n>=i;++i) { if (!in_cir(ans,a[i])) { ans = Circle(a[i],0); for (int j=1;i>j;++j) { if (!in_cir(ans,a[j])) { ans = Circle( (a[i] + a[j])*0.5,dis(a[i],a[j])*0.5 ); for (int k=1;j>k;++k) { if (!in_cir(ans,a[k])) { //get circle cover a_i, a_j, a_k Line l1 = Line( (a[i]+a[j])*0.5,Rotate(a[i]-a[j]) ); Line l2 = Line( (a[i]+a[k])*0.5,Rotate(a[i]-a[k]) ); P tmp = inter(l1,l2); ans = Circle(tmp,dis(tmp,a[i])); } } } } } } return ans; } int extend(int pos,ld limit) { int i; for (i=1;;i = min(i<<1,n-pos+1)) { Circle tmp = min_cir_cover(pos,pos+i-1); if (tmp.r > limit + eps) break; if (i == n-pos + 1) return n; //till the end } int L = pos + (i>>1) - 1,R = pos+i-1; //L is the answer while (L + 1 < R) { int mid = (L+R) >> 1; Circle tmp = min_cir_cover(pos,mid); if (tmp.r < limit + eps) L = mid; else R = mid; } return L; } bool can(ld limit) { int last,cnt=0; for (int i=1;n>=i;i=++last) { if (++cnt == m+1) return false; last = extend(i,limit); } return true; } ld solve() { ld l=0,r=2828500; while (r-l > eps) { ld mid = (l+r)/2; if (can(mid)) r=mid; else l=mid; } return r; } P ans[N]; void show_ans(ld limit) { int m=0; int i,last; for (i=1;n>=i;i=++last) { last = extend(i,limit); Circle tmp = min_cir_cover(i,last); ans[++m] = tmp.p; } cout << m << endl; for (int i=1;m>=i;i++) { cout << ans[i].x << ' ' << ans[i].y << endl; } } int main () { //srand(880301); ios::sync_with_stdio(0); cin.tie(0); cin >>n >> m; for (int i=1;n>=i;++i) { p[i].scan(); } ld ans = solve(); cout << fixed << setprecision(15); cout << ans << endl; show_ans(ans); }
沒有留言:
張貼留言