cjb-poi2011plot
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
{{{
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#define rep(i,n) for(int i=1;i<=n;i++)
#define mp make_pair
#define pb push_back
using namespace std;
#define PI 3.1415926535897932384626433
#define N 200010
#define LF double
int n,m,cnt;
LF R,eps=2e-8;
struct P{LF x,y;}a[N],poi[N],O,ans[N];
map<pair<int,int>,pair<LF,pair<LF,LF> > > fuck;
LF dis(P x,P y){return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}
P center(P x,P y,P z)
{
LF a1=y.x-x.x,b1=y.y-x.y,
c1=(a1*a1+b1*b1)/2.,a2=z.x-x.x,
b2=z.y-x.y,c2=(a2*a2+b2*b2)/2.,
d=a1*b2-a2*b1;
return (P){x.x+(c1*b2-c2*b1)/d,x.y+(a1*c2-a2*c1)/d};
}
LF cal(int l,int r)
{
if (fuck.find(mp(l,r))!=fuck.end())
{
O=(P){fuck[mp(l,r)].second.first,fuck[mp(l,r)].second.second};
return R=fuck[mp(l,r)].first;
}
int i,j,k,n=0;
for(i=l;i<=r;i++)a[n++]=poi[i];
//for(i=0;i<n;i++)swap(a[rand()%n],a[i]);
random_shuffle(a,a+n);
for(O=a[0],R=0,i=1;i<n;i++)if(dis(a[i],O)>R+eps)
for(O=a[i],R=0,j=0;j<i;++j)if(dis(a[j],O)>R+eps){
O=(P){(a[i].x+a[j].x)/2.,(a[i].y+a[j].y)/2.},R=dis(O,a[i]);
for(k=0;k<j;k++)if(dis(a[k],O)>R+eps)O=center(a[k],a[j],a[i]),R=dis(O,a[i]);
}
fuck[mp(l,r)]=mp(R,mp(O.x,O.y));
return R;
}
int getnxt(int i,LF limit)
{
int j;
for(j=1;;j++)
{
cal(i,min(i+(1<<j)-1,n));
if (R>limit+eps)break;
if (i+(1<<j)-1>=n)return n;
}
int l=i+(1<<(j-1)),r=min(i+(1<<j)-1,n),mid;
while (l<r)
{
mid=(l+r)>>1;
cal(i,mid);
if (R>limit+eps)r=mid; else l=mid+1;
}
return l-1;
}
bool check(LF limit)
{
int i=1,j,now; cnt=0;
while (i<=n)
{
if (cnt==m)return 0;
j=getnxt(i,limit);
cnt++;
i=j+1;
}
return 1;
}
int main()
{
scanf("%d%d",&n,&m);
rep(i,n)scanf("%lf%lf",&poi[i].x,&poi[i].y);
LF l=0,r=cal(1,n),mid;
int lim=45;
while (lim-- && r-l>eps)
{
mid=(l+r)/2;
if (check(mid))r=mid; else l=mid;
}
printf("%.15lf\n%d\n",r,m);
int j=1;
rep(i,m)
{
if (j>n){ puts("0 0"); continue; }
int nxt=getnxt(j,r);
cal(j,nxt);
printf("%.15lf %.15lf\n",O.x,O.y);
j=nxt+1;
}
return 0;
}
}}}
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#define rep(i,n) for(int i=1;i<=n;i++)
#define mp make_pair
#define pb push_back
using namespace std;
#define PI 3.1415926535897932384626433
#define N 200010
#define LF double
int n,m,cnt;
LF R,eps=2e-8;
struct P{LF x,y;}a[N],poi[N],O,ans[N];
map<pair<int,int>,pair<LF,pair<LF,LF> > > fuck;
LF dis(P x,P y){return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}
P center(P x,P y,P z)
{
LF a1=y.x-x.x,b1=y.y-x.y,
c1=(a1*a1+b1*b1)/2.,a2=z.x-x.x,
b2=z.y-x.y,c2=(a2*a2+b2*b2)/2.,
d=a1*b2-a2*b1;
return (P){x.x+(c1*b2-c2*b1)/d,x.y+(a1*c2-a2*c1)/d};
}
LF cal(int l,int r)
{
if (fuck.find(mp(l,r))!=fuck.end())
{
O=(P){fuck[mp(l,r)].second.first,fuck[mp(l,r)].second.second};
return R=fuck[mp(l,r)].first;
}
int i,j,k,n=0;
for(i=l;i<=r;i++)a[n++]=poi[i];
//for(i=0;i<n;i++)swap(a[rand()%n],a[i]);
random_shuffle(a,a+n);
for(O=a[0],R=0,i=1;i<n;i++)if(dis(a[i],O)>R+eps)
for(O=a[i],R=0,j=0;j<i;++j)if(dis(a[j],O)>R+eps){
O=(P){(a[i].x+a[j].x)/2.,(a[i].y+a[j].y)/2.},R=dis(O,a[i]);
for(k=0;k<j;k++)if(dis(a[k],O)>R+eps)O=center(a[k],a[j],a[i]),R=dis(O,a[i]);
}
fuck[mp(l,r)]=mp(R,mp(O.x,O.y));
return R;
}
int getnxt(int i,LF limit)
{
int j;
for(j=1;;j++)
{
cal(i,min(i+(1<<j)-1,n));
if (R>limit+eps)break;
if (i+(1<<j)-1>=n)return n;
}
int l=i+(1<<(j-1)),r=min(i+(1<<j)-1,n),mid;
while (l<r)
{
mid=(l+r)>>1;
cal(i,mid);
if (R>limit+eps)r=mid; else l=mid+1;
}
return l-1;
}
bool check(LF limit)
{
int i=1,j,now; cnt=0;
while (i<=n)
{
if (cnt==m)return 0;
j=getnxt(i,limit);
cnt++;
i=j+1;
}
return 1;
}
int main()
{
scanf("%d%d",&n,&m);
rep(i,n)scanf("%lf%lf",&poi[i].x,&poi[i].y);
LF l=0,r=cal(1,n),mid;
int lim=45;
while (lim-- && r-l>eps)
{
mid=(l+r)/2;
if (check(mid))r=mid; else l=mid;
}
printf("%.15lf\n%d\n",r,m);
int j=1;
rep(i,m)
{
if (j>n){ puts("0 0"); continue; }
int nxt=getnxt(j,r);
cal(j,nxt);
printf("%.15lf %.15lf\n",O.x,O.y);
j=nxt+1;
}
return 0;
}