GCJ2009B&JZOJ 4033 Min Perimeter
SOL:
我们参考最近点对的做法,分治加当前最优解剪枝。
#pragma GCC optimize("-Ofast") #include<bits/stdc++.h> using namespace std; #define max(a,b) ((a)<(b)?(b):(a)) #define min(a,b) ((a)<(b)?(a):(b)) #define fo(i,j,k) for (int i=(j);i<=(k);i++) #define fd(i,j,k) for (int i=(j);i>=(k);i--) #define fe(i,j) for (int j=head[i];j!=-1;j=mp[j].next) #define fuck printf("666"\n); #define scan freopen("in.txt","r",stdin) #define print freopen("out.txt","w",stdout) const double inf=1e+20; const int bil=1e+9; struct P { int x,y; }px[100001]; int n; vector<P> py; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x) { char c=nc();int b=1; for (;c<'0'||c>'9';c=nc()) if (c=='-') b=-1; for (x=0;c>='0'&&c<='9';x=x*10+c-'0',c=nc()); x=x*b; } inline void read(long long &x) { char c=nc();int b=1; for (;c<'0'||c>'9';c=nc()) if (c=='-') b=-1; for (x=0;c>='0'&&c<='9';x=x*10+c-'0',c=nc()); x=x*b; } inline bool cmpx(const P& a,const P& b) { if (a.x!=b.x) return a.x<b.x; return a.y<b.y; } inline bool cmpy(const P& a,const P& b) { if (a.y!=b.y) return a.y<b.y; return a.x<b.x; } inline double dis(P a,P b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline double calc(P a,P b,P c) { return dis(a,b)+dis(a,c)+dis(b,c); } double ou,res=inf; void solve(int l,int r,const vector<P> &Py) { // if (r-l+1<3) return inf; if (r-l<10) { for (int i=l;i<r;i++) for (int j=i+1;j<r;j++) for (int k=j+1;k<=r;k++) ou=calc(px[i],px[j],px[k]), res=min(res,ou); return; } int mid=(l+r)/2; int tmp=(px[mid].x+px[mid+1].x)/2; // double res=inf; vector<P> py1;py1.reserve(mid-l+1); vector<P> py2;py2.reserve(r-mid); fo(i,0,(int)Py.size()-1) { if (Py[i].x<tmp) py1.push_back(Py[i]); else py2.push_back(Py[i]); } solve(l,mid,py1),solve(mid+1,r,py2); int up,head=0; if (res>inf/2) up=bil*2; else up=(int)(res/2); static vector<P> temp; temp.clear(); temp.reserve(r-l+1); fo(i,0,r-l) { P p=Py[i]; if (abs(p.x-tmp)>up) continue; while (head<(int)temp.size()&&p.y-temp[head].y>up) head++; fo (i,head,(int)temp.size()-1) { fo(j,i+1,(int)temp.size()-1) res=min(res,calc(p,temp[i],temp[j])); } temp.push_back(p); } return; } int main(int argc, char *argv[]) { read(n); fo(i,1,n) read(px[i].x),read(px[i].y),px[i].x=px[i].x*2-bil/2,px[i].y=px[i].y*2-bil/2,py.push_back(px[i]); sort(px+1,px+n+1,cmpx); sort(py.begin(),py.end(),cmpy); solve(1,n,py); printf("%0.13lf",res/2); return 0; }