Solution : 构造、点到线段的最短距离
Code:
// Beijing 2004 Square
// Solution : 构造
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
#define oo 1e6
#define eps 1e-8
#define nMax 1010
//{
#define pb push_back
#define dbg(x) cerr << __LINE__ << ": " << #x << " = " << x << endl
#define F first
#define S second
#define bug puts("OOOOh.....");
#define zero(x) (((x)>0?(x):-(x))<eps)
#define LL long long
#define DB double
#define sf scanf
#define pf printf
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
double const pi = acos(-1.0);
double const inf = 1e9;
double inline sqr(double x) { return x*x; }
int dcmp(double x){
if(fabs(x)<=eps) return 0;
return x>0?1:-1;
}
//}
// Describe of the 2_K Geomtry
// First Part : Point and Line
// Second Part Cicle
// Third Part Polygan
// First Part:
// ****************************** Point and Line *******************************\\
// {
class point {
public:
double x,y;
point (double x=0,double y=0):x(x),y(y) {}
void make(double _x,double _y) {x=_x;y=_y;}
void read() { scanf("%lf%lf",&x,&y); }
void out() { printf("%.3lf %.3lf\n",x,y);}
double len() { return sqrt(x*x+y*y); }
point friend operator - (point const& u,point const& v) { return point(u.x-v.x,u.y-v.y); }
point friend operator + (point const& u,point const& v) { return point(u.x+v.x,u.y+v.y); }
double friend operator * (point const& u,point const& v){ return u.x*v.y-u.y*v.x; }
double friend operator ^ (point const& u,point const& v) { return u.x*v.x+u.y*v.y; }
point friend operator * (point const& u,double const& k) { return point(u.x*k,u.y*k); }
point friend operator / (point const& u,double const& k) { return point(u.x/k,u.y/k); }
friend bool operator < (point const& u,point const& v){
if(dcmp(v.x-u.x)==0) return dcmp(u.y-v.y)<0;
return dcmp(u.x-v.x)<0;
}
friend bool operator != (point const& u,point const& v){
return dcmp(u.x-v.x) || dcmp(u.y-v.y);
}
point rotate(double s) {
return point(x*cos(s) + y*sin(s),\
-x*sin(s) + y*cos(s));
}
};
typedef point Vector;
typedef class line{
public:
point a,b;
line() {}
line (point a,point b):a(a),b(b){}
void make(point u,point v) {a=u;b=v;}
void read() { a.read(),b.read(); }
}segment;
double det(point u,point v) {
return u.x*v.y - u.y*v.x;
}
double dot(point u,point v) {
return u.x*v.x + u.y*v.y;
}
// Weather P is On the Segment (uv)
int dot_on_seg(point p,point u,point v){
return dcmp(det(p-u,v-p))==0 && dcmp(dot(p-u,p-v)) <= 0; // '>=' means P is u or v
}
// The distance from point p to line l
double PToLine(point p,line l) {
return fabs((p-l.a)*(l.a-l.b))/(l.a-l.b).len();
}
// The ProJect Of Point(p) To Line(l)
point PointProjectLine(point p,line l) {
double t = dot(l.b-l.a,p-l.a)/dot(l.b-l.a,l.b-l.a);
return l.a + (l.b-l.a)*t;
}
// Weather line u parallel line v
int parallel(line u,line v) {
return dcmp(det(u.a-u.b,v.a-v.b))==0;
}
// The Intersection Point Of Line u and Line v
point intersection(line u,line v) {
point ret = u.a;
double t = det(u.a-v.a,v.a-v.b)/det(u.a-u.b,v.a-v.b);
return ret + (u.b-u.a)*t;
}
//}
// ****************************** First Part end ********************************\\
// Second Part:
// ********************************* Circle *************************************\\
// {
struct Circle {
point O;
double r;
Circle() {};
Circle(point O,double r):O(O),r(r){};
};
//}
// ****************************** Second Part End *******************************\\
// Third Part :
// ********************************* Polygan *************************************\\
// {
int ConvexHull(vector<point>& p){
int n=p.size();
int m=0;
vector<point> q;
q.resize(2*n+5);
rep(i,n) {
while(m>1 && dcmp((q[m-1]-q[m-2])*(p[i]-q[m-2])) <= 0) m--;
q[m++] = p[i];
}
int k = m;
for(int i=n-2;i>=0;i--) {
while(m>k && dcmp((q[m-1]-q[m-2])*(p[i]-q[m-2])) <= 0) m--;
q[m++] = p[i];
}
q.resize(m) ;
if(m>1) q.resize(m-1);
// p = q; // 是否修改原来的多边形
return q.size();
}
// 三角形重心
point Center(point a,point b,point c){
return (a+b+c)/3.0;
}
// Centroid of Polygan
point Centroid(vector<point> p){
point O(0,0),ret(0,0);
int n = p.size();
p.pb(p[0]);
double area = 0.0;
rep(i,n) {
ret = ret + Center(O,p[i],p[i+1])*dot(p[i]-O,p[i+1]-O);
area += dot(p[i]-O,p[i+1]-O);
}
if(dcmp(area)==0) {
pf("There maybe something wrong\n");
return p[0];
}
return ret / area;
}
struct Polygan{
vector<point> g;
Polygan() {};
Polygan(vector<point> g):g(g){};
Polygan(point p[],int n) {g.clear();rep(i,n) g.pb(p[i]); };
int convex() { return ConvexHull(g); }
point center() { return Centroid(g); } // 多边形的重心
};
//}
// ******************************* Third Part End ********************************\\
// Solution Part :
typedef point P ;
typedef line L;
double PToSeg(P p,L l){
P s = PointProjectLine(p,l);
if(dot_on_seg(s,l.a,l.b)) return PToLine(p,l);
else return min((p-l.a).len(),(p-l.b).len());
}
double dis(P p,L l[]){
double ans = inf;
for(int i=0;i<5;i++) {
ans = min(ans,PToSeg(p,l[i]));
}
return ans;
}
P p[nMax];
int n;
double cas1() {
point s1=P(0.5/sqrt(3.0),0.5),
s2=P(1.0-0.5/sqrt(3.0),0.5);
line l[5];
l[0]=L(s1,P(0,0)),
l[1]=L(s1,P(0,1)),
l[2]=L(s1,s2),
l[3]=L(s2,P(1,0)),
l[4]=L(s2,P(1,1));
double ans = inf;
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) if(i!=j){
double tmp = (p[i]-s1).len() + (p[j]-s2).len();
for(int k=0;k<n;k++) if(k!=i && k!=j) {
tmp += dis(p[k],l);
}
ans = min(ans,tmp);
}
}
return ans;
}
double cas2() {
point s1=P(0.5,0.5/sqrt(3.0)),
s2=P(0.5,1.0-0.5/sqrt(3.0));
line l[5];
l[0]=L(s1,P(0,0)),
l[1]=L(s1,P(1,0)),
l[2]=L(s1,s2),
l[3]=L(s2,P(0,1)),
l[4]=L(s2,P(1,1));
double ans = inf;
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) if(i!=j){
double tmp = (p[i]-s1).len() + (p[j]-s2).len();
for(int k=0;k<n;k++) if(k!=i && k!=j) {
tmp += dis(p[k],l);
}
ans = min(ans,tmp);
}
}
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
while(sf("%d",&n),n){
rep(i,n) p[i].read();
double ans ;
if(n == 1) {
ans = (p[0]-P(0.5,0.5)).len();
}else {
ans = min(cas1(),cas2());
}
pf("%.3lf\n",ans+eps);
}
return 0;
}