Problem:
Dog Food
ドッグフード
English text is not available in this practice contest.
あなたは, 賢い犬を選ぶコンテストの主催者である．
種目の1つに，以下のようなものがある．
この種目は，平面的な広場の上で行われる．
広場には杭がいくつか立っており，そのうちの1つと，犬はロープで結ばれている．杭やロープの太さは無視できるものとする．ロープが結ばれている杭の座標を(0，0)，犬の位置を(Dx，Dy)とする．
また，ロープが結ばれている杭以外の杭の本数をｎ本とし，それらの座標を(x
1
，y
1
)... (x
n
，y
n
)とする．
初期状態で，ロープはピンと張られた状態である．すなわち，ロープの長さはちょうど(Dx，Dy)と(0，0)の距離に等しく，その2つの端は原点の杭と犬にそれぞれ結び付けられている．
(Fx，Fy)には，ドッグフードがおかれており，この地点がゴールである．この条件下で，短い走行距離でゴールに辿りつけた犬ほど賢いと考えられる．
場合によっては，図F-1のように，直接ゴールに向かうと，別の杭にロープが引っかかり，ロープの長さが足りなくなって，ゴールにたどりつけないため，杭を迂回する必要があることに注意せよ．
この例は，サンプルの1番目の入力を表している．
図 F-1: 杭を迂回する必要がある例
優秀なプログラマーでもあるあなたは，犬がゴールにたどり着けるかどうか，またたどり着けるとしたら最短距離はどうなるのかを，あらかじめ計算しておくことにした．
Input
入力は1つ以上のデータセットからなる．1つのデータセットは次の形式をしている．データセット中の値は，全て整数である．
n
Dx
Dy
Fx
Fx
x
1
y
1
...
x
n
y
n
n はロープが繋がっていない杭の本数を表す．
Dx, Dy は，犬の初期位置の座標を表す．
Fx, Fy は，ゴールの位置を表す．
x
i
, y
i
は，ロープが繋がっていない杭の座標を表す．
データセットについて，つぎの制約が成立している．
1 ≤ n ≤ 8
-100 ≤ Dx, Dy, Fx, Fy, x
i
, y
i
≤ 100
線分(0,0), (Dx,Dy)上に杭は存在しない.
(0,0), (Dx, Dy), (Fx, Fy), (x
1
, y
1
), (x
2
, y
2
)... (x
n
, y
n
) はすべて異なる座標である.
また，以下のことを仮定してよい.
(Dx,Dy) が原点方向に対して, ε(|ε| < 0.00001)だけ変化したとき, 結果が 0.0005 より大きく変化することはない．
入力の終わりは，0を1つだけ含む行で表される．
Output
各データセットについて，ゴールにたどり着ける場合は最短距離を，たどり着けない場合は-1を 1 行に出力せよ．
出力には, 0.001を超える誤差があってはならない.
Sample Input
1
-4 -8
3 -8
0 -6
1
0 6
4 0
1 4
1
4 0
0 6
1 4
4
95 0
0 90
55 64
33 31
5 4
15 43
8
100 100
99 -100
60 50
6 5
12 10
24 20
30 0
70 0
-30 -10
-90 -30
0
図F-2, F-3, F-4 は，それぞれサンプルの2番目から4番目の配置を示している．
図 F-2: 2番目のサンプル
図 F-3: 3番目のサンプル
図 F-4: 4番目のサンプル
Output for Sample Input
8.0776872
7.2360679
-1
140.2870005
273.9090890

Submitted solutions:

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
using namespace std;

const double EPS = 1e-10;
const double INF = 1e12;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};

namespace std{
    bool operator < (const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(abs(c)-abs(b) > EPS) return -2; //a-b-c
    return 0; //a-c-b
}

bool intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS  && dot(s[0]-p, s[1]-p)<EPS;
}

int in_poly(const P &p, const VP &poly){
    int n = poly.size();
    int ret = -1;
    for(int i=0; i<n; i++){
        P a = poly[i]-p;
        P b = poly[(i+1)%n]-p;
        if(a.Y > b.Y) swap(a,b);
        if(intersectSP(L(a,b), P(0,0))) return 0;
        if(a.Y<=0 && b.Y>0 && cross(a,b)<0) ret = -ret;
    }
    return ret;
}

VP convex(VP v){
    VP ret;
    int n = v.size();
    sort(v.begin(), v.end());
    for(int i=0; i<n; i++){
        while((int)ret.size()>1 && cross(ret.back()-ret[ret.size()-2], v[i]-ret.back()) < EPS){
            ret.pop_back();
        }
        ret.push_back(v[i]);
    }
    int t = ret.size();
    for(int i=n-2; i>=0; i--){
        while((int)ret.size()>t && cross(ret.back()-ret[ret.size()-2], v[i]-ret.back()) < EPS){
            ret.pop_back();
        }
        ret.push_back(v[i]);
    }
    if((int)ret.size() > 1) ret.pop_back();
    return ret;
}

vector<bool> used(10, false);
double limit;
double solve(P pos, P goal, P pivot, double len, VP &pin){
	if(len + abs(pos-pivot) > limit +EPS) return INF;
	if(pos == goal) return 0;
	
	int n = pin.size()-2;
	double dist = INF;
	for(int i=0; i<n+2; i++){
		if(used[i]) continue;
		used[i] = true;
		
		P newpivot = pivot;
		double newlen = len;
		
		VP tri{pos, pin[i], pivot};
		if(ccw(tri[0], tri[1], tri[2]) == -1) swap(tri[1], tri[2]);
		VP plist{pivot, pin[i]};
		for(int j=0; j<n+1; j++){
			if(in_poly(pin[j], tri) == 1){
				plist.push_back(pin[j]);
			}
		}
		sort(plist.begin(), plist.end());
		plist.erase(unique(plist.begin(), plist.end()), plist.end());
		
		if((int)plist.size() >= 3){
			VP cvx = convex(plist);
			for(int j=0; j<(int)cvx.size(); j++){
				if(cvx[j] == pivot){
					cvx.insert(cvx.end(), cvx.begin(), cvx.begin()+j);
					cvx.erase(cvx.begin(), cvx.begin()+j);
					break;
				}
			}
			if(cvx[1] == pin[i]) reverse(cvx.begin()+1, cvx.end());
			for(int j=0; j<(int)cvx.size()-2; j++){
				newlen += abs(cvx[j+1] -cvx[j]);
			}
			newpivot = *(cvx.end() -2);
		}
		
		P online(INF, INF);
		for(int j=0; j<=n; j++){
			if(intersectSP(L(newpivot, pin[i]), pin[j]) && pin[j]!=newpivot && i!=j){
				if(abs(pin[i] -online) > abs(pin[i] -pin[j])){
					online = pin[j];
				}
			}
		}
		if(online!=P(INF, INF)){
			newlen += abs(newpivot -online);
			newpivot = online;
		}
		dist = min(dist, solve(pin[i], goal, newpivot, newlen, pin) +abs(pos-pin[i]));
		
		used[i] = false;
	}
	return dist;
}

int main(){
	cout << fixed;
	cout << setprecision(10);
	
	while(1){
		int n;
		cin >> n;
		if(n==0) break;
		
		double x,y;
		P s,g;
		cin >> x >> y;  s = P(x, y);
		cin >> x >> y;  g = P(x, y);
		
		VP pin(n+2); //0:スタート, 1~n:杭, n+1:ゴール
		pin[0] = P(0, 0);
		for(int i=1; i<=n; i++){
			cin >> x >> y;
			pin[i] = P(x, y);
		}
		pin[n+1] = g;
		limit = abs(s);
		
		if(abs(g) > abs(s) +EPS){
			cout << -1 << endl;
		}else{
			double ans = solve(s, g, pin[0], 0, pin);
			cout << ans << endl;
		}
	}
    return 0;
}
accuracy: 1
time_ms: 3740
memory_kb: 3336
final_rank: 10

code_snippet: #include<bits/stdc++.h>
#define inf 1<<29
#define linf 1e16
#define eps (1e-8)
#define mod 1000000007
#define pi acos(-1)
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return (x!=p.x ? x<p.x : y<p.y);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

Polygon convex_hull(Polygon s){
  Polygon g;
  int n=s.size();
  if(n<3)return s;

  sort(s.begin(),s.end());

  for(int i=0;i<n;i++){
    for(int n=g.size();n>=2&&ccw(g[n-2],g[n-1],s[i])==1;n--){
      g.pop_back();
    }
    g.push_back(s[i]);
  }
  for(int i=n-2;i>=0;i--){
    for(int n=g.size();n>=2&&ccw(g[n-2],g[n-1],s[i])==1;n--){
      g.pop_back();
    }
    g.push_back(s[i]);
  }
  reverse(g.begin(),g.end());
  g.pop_back();
  return g;
}

double getCircumference(Polygon p){
  int n=p.size();
  double res=0;
  FOR(i,0,n)res+=abs(p[i]-p[(i+1)%n]);
  return res;
}

int n;
Point s,t;
vector<Point> vp;
bool used[10]={};

bool check(Point p,Point o,Point d,double dis){
  Polygon tr,cp;
  tr.pb(o);
  tr.pb(p);
  tr.pb(d);
  cp.pb(d);
  cp.pb(o);
  FOR(i,0,n){
    if(p==vp[i])continue;
    if(d==vp[i])continue;
    if(contains(tr,vp[i]))cp.pb(vp[i]);
  }
  cp = convex_hull(cp);
  if(getCircumference(cp)+dis-abs(d-o)-abs(s)<-eps)return true;
  return false;
}

pair<Point,double> getm(Point p,Point o,Point d){
  Polygon tr,cp;
  tr.pb(o);
  tr.pb(p);
  tr.pb(d);
  cp.pb(d);
  cp.pb(o);
  FOR(i,0,n){
    if(p==vp[i])continue;
    if(d==vp[i])continue;
    if(contains(tr,vp[i]))cp.pb(vp[i]);
  }
  cp = convex_hull(cp);
  Point res;
  FOR(i,0,cp.size())
    if(cp[i]==d && cp[(i+1)%cp.size()]==o)
      res = cp[(i-1+cp.size())%cp.size()];
  reverse(all(cp));
  FOR(i,0,cp.size())
    if(cp[i]==d && cp[(i+1)%cp.size()]==o)
      res = cp[(i-1+cp.size())%cp.size()];
  return mp(res,getCircumference(cp)-abs(d-o)-abs(res-d));
}

double rec(Point p,Point o,double dis,double sum){
  double res = inf;
  if(check(p,o,t,dis))return sum+abs(p-t);
  FOR(i,0,n){
    if(used[i])continue;
    used[i]=true;
    if(check(p,o,vp[i],dis)){
      pair<Point,double> no = getm(p,o,vp[i]);
      res=min(res,rec(vp[i],no.f,no.s+dis,sum+abs(vp[i]-p)));
    }
    used[i]=false;
  }
  return res;
}

double solve(){
  if(abs(s)<abs(t))return -1;
  double res=abs(s)+abs(t);
  res = min(res,rec(s,Point(0,0),0,0));
  return res;
}

int main()
{
  while(cin>>n && n){
    cin>>s.x>>s.y>>t.x>>t.y;
    vp.clear();
    FOR(i,0,n){
      int x,y;
      cin>>x>>y;
      vp.pb(Point(x,y));
    }
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 820
memory_kb: 3208
final_rank: 8

code_snippet: #include<cstdio>
#include<complex>
#include<cmath>
#include<vector>
#include<algorithm>

using namespace std;

typedef double Real;

typedef complex<Real> Point;
typedef complex<Real> Vector;
typedef pair<Point,Point> Segment;
typedef vector<Point> Polygon;
typedef pair<Point,Point> Line;

const Real eps=1e-9;
const Real PI=acos(-1.0);

template<class T> bool eq(T a,T b){
	return abs(a-b)<eps;
}
template<class T> int sgn(T a){
	if(eq(a,0.0)) return 0;
	if(a>0) return 1;
	return -1;
}

Real arg(Vector a){
	return atan2(a.imag(),a.real());
}

Real doP(Vector a,Vector b){
	return (conj(a)*b).real();
}

Real crP(Vector a,Vector b){
	return (conj(a)*b).imag();
}

Point iLL(Line l1,Line l2){
	Point a=l1.first,b=l1.second;
	Point c=l2.first,d=l2.second;
	Real num=crP(c-a,d-a);
	Real den=crP(b-a,d-c);
	return a+(b-a)*num/den;
}

Point start,goal;
Point pts[10];
int N;

struct State{
	Point center;
	Real radius;
	Point start,goal;
	State(){}
	bool isValid(){
		if(sgn(abs(goal-center)-radius)>0) return false;
		return true;
	}
	State getNext(){
		if(sgn(crP(goal-start,-start))==0){
			State res(*this);
			res.start=goal;
			return res;
		}
		Real curAng=-1;
		Real curDis=-1;
		Point nxtCenter=center;
		for(int i=0;i<N;i++){
			Point p=pts[i];
			int s1=sgn(crP(goal-start,p-start));
			int s2=sgn(crP(center-goal,p-goal));
			int s3=sgn(crP(start-center,p-center));
			if(s1*s3==0) continue;
			if(s2==0) s2=s1;
			if(s1!=s2||s1!=s3) continue;
			Real num=arg((p-center)/(start-center));
			Real den=arg((goal-center)/(start-center));
			Real ang=num/den;
			Real dis=abs(p-center);
			if(eq(curAng,-1.0)||sgn(curAng-ang)>0||(sgn(curAng-ang)==0&&sgn(curDis-dis)<0)){
				nxtCenter=p;
				curAng=ang;
				curDis=dis;
			}
		}
		if(eq(nxtCenter,center)){
			State res(*this);
			res.start=goal;
			return res;
		}
		Point nxtStart=iLL(Line(center,nxtCenter),Line(start,goal));
		State res;
		res.start=nxtStart;
		res.goal=goal;
		res.radius=radius-abs(nxtCenter-center);
		res.center=nxtCenter;
		return res;
	}
};

Point readP(){
	int x,y;
	scanf("%d%d",&x,&y);
	return Point(x,y);
}

void input(){
	scanf("%d",&N);
	if(N==0) exit(0);
	start=readP();
	goal=readP();
	for(int i=0;i<N;i++) pts[i]=readP();
	pts[N]=start;
	pts[N+1]=goal;
}

vector<vector<int> > ord;

vector<int> vec;
bool used[8];
void dfs(){
	vec.push_back(N+1);
	ord.push_back(vec);
	vec.pop_back();
	for(int i=0;i<N;i++){
		if(used[i]) continue;
		vec.push_back(i);
		used[i]=true;
		dfs();
		used[i]=false;
		vec.pop_back();
	}
}

int main(){
	while(true){
		input();
		vec.clear();
		vec.push_back(N);
		ord.clear();
		for(int i=0;i<N;i++) used[i]=false;
		dfs();
		Real ans=-1;
		for(int i=0;i<ord.size();i++){
			vector<int> ord=::ord[i];
			Real dis=0;
			State state;
			state.start=pts[ord[0]];
			state.radius=abs(start);
			state.center=Point(0,0);
			bool suc=true;
			for(int j=1;j<ord.size();j++){
				state.goal=pts[ord[j]];
				dis+=abs(pts[ord[j]]-pts[ord[j-1]]);
				while(true){
					if(state.isValid()==false){
						suc=false;
						break;
					}
					state=state.getNext();
					if(eq(state.start,state.goal)) break;
				}
			}
			if(suc){
				if(eq(ans,-1.0)||sgn(ans-dis)>0){
					ans=dis;
				}
			}
		}
		if(ans<0){
			printf("-1\n");
		}else{
			printf("%f\n",ans);
		}
	}
	return 0;
}
accuracy: 1
time_ms: 2330
memory_kb: 11512
final_rank: 12

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <iterator>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) container.begin(), container.end()
#define RALL(container) container.rbegin(), container.rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}

#include <complex>
#include <cmath>
#define EPS 1.0e-10
#define INF 1.0e5
#define PI 3.1415926535897932384 

// テ・ツョツ淌ヲツ閉ーテ」ツ?ョテァツャツヲテ・ツ渉キテゥツ鳴「テヲツ閉ー
inline int signum(double x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
//XYテ・ツコツァテヲツィツ?
#define X real()
#define Y imag()
// テァツつケ
typedef complex<double> P;
 

// テァツキツ堙・ツ按?」ツδサテ・ツ債甘ァツ崢エテァツキツ堙」ツδサテァツ崢エテァツキツ?
struct L { P pos, dir; L(P p=P(), P d=P()):pos(p),dir(d){}};

// テ・ツ、ツ堙ィツァツ津・ツスツ「
typedef vector<P> G;
 
// テ・ツ??
struct C { P p; double r; };

// std::norm テ」ツ?ッabs(p)*abs(p)テ」ツ?ェテ」ツ?ョテ」ツ?ァテゥツ??」ツ??
inline double norm(P p){
	return p.X*p.X+p.Y*p.Y;
}

// テ、ツコツ古」ツ?、テ」ツ?ョテ」ツδ凖」ツつッテ」ツδ暗」ツδォテ」ツ?ョテ・ツ??ァツゥツ催」ツつ津ィツィツ暗ァツョツ療」ツ?凖」ツつ?
inline double inp(const P& a, const P& b) {
	return (conj(a)*b).real();
}
 
// テ、ツコツ古」ツ?、テ」ツ?ョテ」ツδ凖」ツつッテ」ツδ暗」ツδォテ」ツ?ョテ・ツ、ツ姪ァツゥツ催」ツつ津ィツィツ暗ァツョツ療」ツ?凖」ツつ?
inline double outp(const P& a, const P& b) {
	return (conj(a)*b).imag();
}

inline int ccw(const P& p, const P& r, const P& s) {
    P a(r-p), b(s-p);
    int sgn = signum(outp(a, b));
    if (sgn != 0)
        return sgn;
    if (a.real()*b.real() < -EPS || a.imag()*b.imag() < -EPS)
        return -1;
    if (norm(a) < norm(b) - EPS)
        return 1;
    return 0;
}

bool sp_intersects(const L& s, const P& p) {
    return ( abs(s.pos - p) + abs(s.pos + s.dir - p) - abs(s.dir) < EPS );
}
bool insideP(G& g, const P& p) {
	if(ccw(g[0], g[1], g[2]) != 1) swap(g[1], g[2]);
	if(norm(g[0]-p) < EPS || norm(g[1]-p) < EPS || norm(g[2]-p) < EPS) return false;
    double sum = 0.0;
    int n = g.size();
    if(n && g[0] == p) return false;
    for(int i = 0; i < n; i++) {
        int j = (i+1)%n;
        if (sp_intersects(L(g[i], g[j]-g[i]), p))
            return true;
        sum += arg((g[j]-p)/(g[i]-p));
    }
    return (abs(sum) > 1);
}

bool xy_less(const P& a, const P& b) {
    if (abs(a.imag()-b.imag()) < EPS) return (a.real() < b.real());
    return (a.imag() < b.imag());
}
template<class IN>
void walk_rightside(IN begin, IN end, vector<P>& v) {
    IN cur = begin;
    v.push_back(*cur++);
    vector<P>::size_type s = v.size();
    v.push_back(*cur++);
    while(cur != end) {
        if (v.size() == s || ccw(v[v.size()-2], v.back(), *cur) > EPS)
            v.push_back(*cur++);
        else
            v.pop_back();
    }
    v.pop_back();
}
//テ・ツ?クテ・ツ個?」ツつ津ヲツアツづ」ツつ?」ツつ?
vector<P> convex_hull(vector<P> v) {
    if (v.size() <= 1)
        return v; // EXCEPTIONAL
    sort(v.begin(), v.end(), xy_less);
    vector<P> cv;
    walk_rightside(v.begin(), v.end(), cv);
    walk_rightside(v.rbegin(), v.rend(), cv);
    return cv;
}

int n;
P S, T;

double dfs(P S1, P S2, vector<P> p, double l){
//	cout << "(" << S1 << ", " << S2  << ", " << l << ") start" << endl;
	G g, g2;
	g.push_back(S1);
	g.push_back(S2);
	g.push_back(T);
	g2.push_back(S1);
	g2.push_back(T);
	REP(i, p.size()) if(insideP(g, p[i])) g2.push_back(p[i]);
	g2 = convex_hull(g2);
	double sum = 0;
	if(g2.size() == 2 && abs(T-S1) < l+EPS){
//		cout << "3(" << S1 << ", " << S2  << ", " << l << ") = " << abs(S2-T) << endl << endl;
		return abs(S2-T);
	}
	REP(i, g2.size()) sum += abs(g2[i]-g2[(i+1)%g2.size()]);
	if(sum - abs(T-S1) < l+EPS){
//		cout << "2(" << S1 << ", " << S2  << ", " << l << ") = " << abs(S2-T) << endl << endl;
		return abs(S2-T);
	}
	double res = INF;
	REP(i, p.size()){
		if(norm(p[i]-S2) < EPS || !insideP(g, p[i])) continue;
//		cout << "!" << p[i] << endl;
		G g, g2;
		g.push_back(S1);
		g.push_back(S2);
		g.push_back(p[i]);
		g2.push_back(S1);
		g2.push_back(p[i]);
		REP(j, p.size()) if(i!=j && insideP(g, p[j])) g2.push_back(p[j]);
		g2 = convex_hull(g2);
//		cout << g2 << endl;
		double sum = 0;
		if(g2.size() == 2 && abs(p[i]-S1) < l+EPS) chmin(res, abs(S2-p[i]) + dfs(S1, p[i], p, l));
		REP(j, g2.size()) sum += abs(g2[j]-g2[(j+1)%g2.size()]);
		
		if(sum - abs(p[i]-S1) < l+EPS){
			P prev;
			REP(j, g2.size()) if(abs(g2[j]-p[i])<EPS) prev = g2[(j+g2.size()-1)%g2.size()];
//			cout << g2 << endl;
//			cout << "prev is " << prev << endl;
//			cout << "dfs" << prev << "," << p[i] << endl;
			chmin(res, abs(S2-p[i]) + dfs(prev, p[i], p, l-(sum - abs(p[i]-S1) - abs(p[i]-prev))));
		}
	}
//	cout << "1(" << S1 << ", " << S2 << ", " << l << ") = " << res << endl << endl;
	return res;
}

main(){
	while(cin >> n, n){
		vector<P> p;
		cin >> S.X >> S.Y >> T.X >> T.Y;
		REP(i, n){
			double x, y;
			cin >> x >> y;
			p.push_back(P(x, y));
		}
		if(ccw(P(0, 0), S, T) == -1){
			REP(i, n) p[i].Y = -p[i].Y;
			S.Y = -S.Y;
			T.Y = -T.Y;
		}
		double ret = dfs(P(0, 0), S, p, abs(S));
		if(ret > 90000) puts("-1");
		else printf("%.9f\n", ret);
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1376
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for(int i=0; i<(int)(n); i++)
#define rep(i,n) for(int i=0; i<(int)(n); i++)
typedef complex<double> P;
typedef vector<P> L;
P input() {
    double x, y;
    cin >> x >> y;
    return P(x, y);
}
const double EPS = 1e-8;
int sign(double x) {
    if(x > EPS) return 1;
    if(x < -EPS) return -1;
    return 0;
}
double dot(P a, P b) {
    return real(conj(a) * b);
}
double cross(P a, P b) {
    return imag(conj(a) * b);
}
P vec(L l) {
    return l[1] - l[0];
}
bool iLS(L l, L s) {
    return sign(cross(vec(l), s[0] - l[0]) * cross(vec(l), s[1] - l[0])) <= 0;
}

vector<P> pLL(L l, L m) {
    double A = cross(vec(l), vec(m));
    double B = cross(vec(l), l[1] - m[0]);
    if(sign(A) == 0 && sign(B) == 0) return {l[0], l[1], m[0], m[1]};
    if(sign(A) == 0) return {};
    return {m[0] + vec(m) * B / A};
}
const double INF = 1e10;
namespace std{
    bool operator < (const P& a, const P& b) {
        if(a.real() != b.real()) return a.real() < b.real();
        else return a.imag() < b.imag();
    }
};

int cnt;
map< tuple<P, P, double>, double> memo;
double calc(P dog, P fix, double length, P G, const vector<P>& rod, set<P> used=set<P>()) {
    auto t = make_tuple(dog, fix, length);
    if(sign(abs(dog - G)) == 0) return 0;
    if(sign(length - abs(fix - G)) < 0) return INF;
    if(memo.count(t)) return memo[t];

    //cout << dog << " " << fix << endl;

    vector<P> search = rod;
    search.push_back(G);
    double res = INF;
    for(P to : search) if(abs(dog - to) > EPS) {
        L path = {dog, to};
        vector<pair<P, P>> cand;
        for(int i = 0; i < rod.size(); i++) {
            if(sign(abs(rod[i] - dog)) == 0) continue;
            L line = {fix, rod[i]};
            if(iLS(line, path)) {
                vector<P> cpv = pLL(line, path);
                if(cpv.size() > 1) continue; // is it right??
                P cp = cpv[0];
                if(dot(rod[i] - fix, cp - fix) < 0) continue;
                if(sign(abs(rod[i] - fix) - abs(cp - fix)) >= 0) continue;
                cand.push_back(make_pair(cp, rod[i]));
            }
        }

        if(cand.empty()){
            if(!used.count(to)) {
                set<P> used2 = used;
                used2.insert(to);
                res = min(res, abs(to - dog) + calc(to, fix, length, G, rod, used2));
            }
            continue;
        }

        sort(cand.begin(), cand.end(),
                [&](pair<P, P> c1, pair<P, P> c2) {
                    P p1, r1, p2, r2;
                    tie(p1, r1) = c1;
                    tie(p2, r2) = c2;
                    int sp = sign( abs(dog - p1) - abs(dog - p2) );
                    int sr = sign( abs(fix - r1) - abs(fix - r2) );
                    return sp < 0 || (sp == 0 && sr > 0);
                    });

        P ndog, nfix;
        tie(ndog, nfix) = cand[0];
        double nlength = length - abs(nfix - fix);
        //cout << "p1: " << dog << " " << fix << " " << length << "->" << 
        //    ndog << " " << nfix << " " << nlength << endl;
        res = min(res, abs(dog - ndog) + calc(ndog, nfix, nlength, G, rod, used));
        //cout << "p2: " << dog << " " << fix << " " << length << "->" << 
        //    nfix << " " << fix << " " << length << endl;
        if(!used.count(nfix)){
            set<P> used2 = used;
            used2.insert(nfix);
            res = min(res, abs(dog - nfix) + calc(nfix, fix, length, G, rod, used2));
        }
    }
    return memo[t] = res;
}
int main() {
    int n;
    while(cin >> n && n > 0) {
        P dog = input();
        P goal = input();
        P fix = {0, 0};
        vector<P> rod(n);
        REP(i, n) rod[i] = input();
        memo.clear();
        double ans = calc(dog, fix, abs(dog - fix),goal, rod);
        if(ans >= INF) {
            cout << -1 << endl;
        } else {
            printf("%.7f\n", ans);
        }
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1368
final_rank: 4

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <iterator>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) container.begin(), container.end()
#define RALL(container) container.rbegin(), container.rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}

#include <complex>
#include <cmath>
#define EPS 1.0e-10
#define INF 1.0e5
#define PI 3.1415926535897932384 

// 実数の符号関数
inline int signum(double x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
//XY座標
#define X real()
#define Y imag()
// 点
typedef complex<double> P;
 

// 線分・半直線・直線
struct L { P pos, dir; L(P p=P(), P d=P()):pos(p),dir(d){}};

// 多角形
typedef vector<P> G;
 
// 円
struct C { P p; double r; };

// std::norm はabs(p)*abs(p)なので遅い
inline double norm(P p){
	return p.X*p.X+p.Y*p.Y;
}

// 二つのベクトルの内積を計算する
inline double inp(const P& a, const P& b) {
	return (conj(a)*b).real();
}
 
// 二つのベクトルの外積を計算する
inline double outp(const P& a, const P& b) {
	return (conj(a)*b).imag();
}

inline int ccw(const P& p, const P& r, const P& s) {
    P a(r-p), b(s-p);
    int sgn = signum(outp(a, b));
    if (sgn != 0)
        return sgn;
    if (a.real()*b.real() < -EPS || a.imag()*b.imag() < -EPS)
        return -1;
    if (norm(a) < norm(b) - EPS)
        return 1;
    return 0;
}

bool sp_intersects(const L& s, const P& p) {
    return ( abs(s.pos - p) + abs(s.pos + s.dir - p) - abs(s.dir) < EPS );
}
bool insideP(G& g, const P& p) {
	if(ccw(g[0], g[1], g[2]) != 1) swap(g[1], g[2]);
	if(norm(g[0]-p) < EPS || norm(g[1]-p) < EPS || norm(g[2]-p) < EPS) return false;
    double sum = 0.0;
    int n = g.size();
    if(n && g[0] == p) return false;
    for(int i = 0; i < n; i++) {
        int j = (i+1)%n;
        if (sp_intersects(L(g[i], g[j]-g[i]), p))
            return true;
        sum += arg((g[j]-p)/(g[i]-p));
    }
    return (abs(sum) > 1);
}

bool xy_less(const P& a, const P& b) {
    if (abs(a.imag()-b.imag()) < EPS) return (a.real() < b.real());
    return (a.imag() < b.imag());
}
template<class IN>
void walk_rightside(IN begin, IN end, vector<P>& v) {
    IN cur = begin;
    v.push_back(*cur++);
    vector<P>::size_type s = v.size();
    v.push_back(*cur++);
    while(cur != end) {
        if (v.size() == s || ccw(v[v.size()-2], v.back(), *cur) > EPS)
            v.push_back(*cur++);
        else
            v.pop_back();
    }
    v.pop_back();
}
//凸包を求める
vector<P> convex_hull(vector<P> v) {
    if (v.size() <= 1)
        return v; // EXCEPTIONAL
    sort(v.begin(), v.end(), xy_less);
    vector<P> cv;
    walk_rightside(v.begin(), v.end(), cv);
    walk_rightside(v.rbegin(), v.rend(), cv);
    return cv;
}

int n;
P S, T;

double dfs(P S1, P S2, vector<P> p, double l){
//	cout << "(" << S1 << ", " << S2  << ", " << l << ") start" << endl;
	G g, g2;
	g.push_back(S1);
	g.push_back(S2);
	g.push_back(T);
	g2.push_back(S1);
	g2.push_back(T);
	REP(i, p.size()) if(insideP(g, p[i])) g2.push_back(p[i]);
	g2 = convex_hull(g2);
	double sum = 0;
	if(g2.size() == 2 && abs(T-S1) < l+EPS){
//		cout << "3(" << S1 << ", " << S2  << ", " << l << ") = " << abs(S2-T) << endl << endl;
		return abs(S2-T);
	}
	REP(i, g2.size()) sum += abs(g2[i]-g2[(i+1)%g2.size()]);
	if(sum - abs(T-S1) < l+EPS){
//		cout << "2(" << S1 << ", " << S2  << ", " << l << ") = " << abs(S2-T) << endl << endl;
		return abs(S2-T);
	}
	double res = INF;
	REP(i, p.size()){
		if(norm(p[i]-S2) < EPS || !insideP(g, p[i])) continue;
//		cout << "!" << p[i] << endl;
		G g, g2;
		g.push_back(S1);
		g.push_back(S2);
		g.push_back(p[i]);
		g2.push_back(S1);
		g2.push_back(p[i]);
		REP(j, p.size()) if(i!=j && insideP(g, p[j])) g2.push_back(p[j]);
		g2 = convex_hull(g2);
//		cout << g2 << endl;
		double sum = 0;
		if(g2.size() == 2 && abs(p[i]-S1) < l+EPS) chmin(res, abs(S2-p[i]) + dfs(S1, p[i], p, l));
		REP(j, g2.size()) sum += abs(g2[j]-g2[(j+1)%g2.size()]);
		
		if(sum - abs(p[i]-S1) < l+EPS){
			P prev;
			REP(j, g2.size()) if(abs(g2[j]-p[i])<EPS) prev = g2[(j+g2.size()-1)%g2.size()];
//			cout << g2 << endl;
//			cout << "prev is " << prev << endl;
//			cout << "dfs" << prev << "," << p[i] << endl;
			chmin(res, abs(S2-p[i]) + dfs(prev, p[i], p, l-(sum - abs(p[i]-S1) - abs(p[i]-prev))));
		}
	}
//	cout << "1(" << S1 << ", " << S2 << ", " << l << ") = " << res << endl << endl;
	return res;
}

main(){
	while(cin >> n, n){
		vector<P> p;
		cin >> S.X >> S.Y >> T.X >> T.Y;
		REP(i, n){
			double x, y;
			cin >> x >> y;
			p.push_back(P(x, y));
		}
		if(ccw(P(0, 0), S, T) == -1){
			REP(i, n) p[i].Y = -p[i].Y;
			S.Y = -S.Y;
			T.Y = -T.Y;
		}
		double ret = dfs(P(0, 0), S, p, abs(S));
		if(ret > 90000) puts("-1");
		else printf("%.9f\n", ret);
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1376
final_rank: 5

code_snippet: #include <cstdio>
#include <vector>
#include <algorithm>
#include <utility>
#include <complex>
#include <cmath>
using namespace std;

typedef complex<double> P;
typedef const P &rP;

#define EPS 1e-7

double ans;
vector<P> pnts;

double dot(rP va, rP vb){
	return real(va) * real(vb) + imag(va) * imag(vb);
}

double cross(rP a, rP b){
	return real(a) * imag(b) - imag(a) * real(b);
}

double distance_ls_p(rP a, rP b, rP c){
	if( dot(b - a, c - a) <= 0.0 ) return abs(c - a);
	if( dot(a - b, c - b) <= 0.0 ) return abs(c - b);
	return abs(cross(b - a, c - a)) / abs(b - a);
}

bool contains(const vector<P> &plg, rP pt){
	int cnt = 0;
	double y = imag(pt);

	for(int i = 0; i < plg.size(); ++i){
		int j = (i + 1 == plg.size() ? 0: i + 1);

		if( distance_ls_p(plg[i], plg[j], pt) < EPS ){
			return false;
		}

		double dyi = imag(plg[i]) - y;
		double dyj = y - imag(plg[j]);
		double tx = (dyi * real(plg[j]) + dyj * real(plg[i])) / (dyi + dyj);

		if(imag(plg[i]) >= y && imag(plg[j]) < y){
			if( tx < real(pt) ) ++cnt;
		}
		else if(imag(plg[i]) < y && imag(plg[j]) >= y){
			if( tx < real(pt) ) ++cnt;
		}
	}

	return (cnt % 2 != 0);
}

P intersect(rP pa1, rP pa2, rP pb1, rP pb2){
	P da12 = pa2 - pa1;
	P db21 = pb1 - pb2;
	P dab1 = pb1 - pa1;
	double D = cross(da12, db21);
	double t = cross(dab1, db21) / D;
	return pa1 + t * da12;
}


void dfs(int now, rP prev, int S, double len, double sum){
	if(now == 1){
		ans = min(ans, sum);
		return;
	}

	vector<P> tri(3);

	for(int i = 1; i < pnts.size(); ++i){
		if(S >> i & 1){ continue; }
		if(abs(cross(pnts[now], pnts[i])) < EPS){
			continue;
		}

		int T = S | 1 << i;
		double nl = len;
		P base = prev;
		P pos = pnts[now];

		while(1){
			int idx = -1;
			double minarg = 9.9;
			double maxnorm = -1.0;

			tri[0] = base;
			tri[1] = pos;
			tri[2] = pnts[i];
			for(int j = 2; j < pnts.size(); ++j){
				if(!contains(tri, pnts[j])){
					bool cntn = false;
					for(int k = 0; k < 3; ++k){
						if(norm(pnts[j] - tri[k]) < EPS){
							cntn = true;
							break;
						}
					}
					if(cntn){
						continue;
					}

					double d1 = abs(pnts[j] - base), d2 = abs(pnts[j] - pnts[i]);
					double d3 = abs(pnts[i] - base);
					if(abs(d1 + d2 - d3) > EPS){
						continue;
					}
				}
				double a = abs(arg((pnts[j] - base) / (pos - base)));
				double nm = norm(pnts[j] - base);
				if(a + EPS < minarg){
					minarg = a;
					maxnorm = nm;
					idx = j;
				}
				else if(abs(a - minarg) < EPS && maxnorm < nm){
					minarg = a;
					maxnorm = nm;
					idx = j;
				}
			}

			if(idx == -1) break;

			pos = intersect(pos, pnts[i], base, pnts[idx]);
			nl -= abs(pnts[idx] - base);
			base = pnts[idx];
			T |= 1 << idx;
		}

		if(nl > abs(pnts[1] - base) - EPS){
			dfs(i, base, T, nl, sum + abs(pnts[now] - pnts[i]));
		}
	}
}


int main(){
	int n, x, y;
	while(scanf("%d", &n), n){
		pnts.resize(n + 2);
		for(int i = 0; i < n + 2; ++i){
			scanf("%d%d", &x, &y);
			pnts[i] = P(x, y);
		}

		if(norm(pnts[0]) < norm(pnts[1])){
			puts("-1");
		}
		else{
			ans = abs(pnts[0]) + abs(pnts[1]);
			dfs(0, P(), 1, abs(pnts[0]), 0.0);
			printf("%f\n", ans);
		}
	}
}
accuracy: 1
time_ms: 410
memory_kb: 1172
final_rank: 7

code_snippet: #include <cstdio>
#include <vector>
#include <algorithm>
#include <utility>
#include <complex>
#include <cmath>
using namespace std;

typedef complex<double> P;
typedef const P &rP;

#define EPS 1e-7

double ans;
vector<P> pnts;

double dot(rP va, rP vb){
	return real(va) * real(vb) + imag(va) * imag(vb);
}

double cross(rP a, rP b){
	return real(a) * imag(b) - imag(a) * real(b);
}

double distance_ls_p(rP a, rP b, rP c){
	if( dot(b - a, c - a) <= 0.0 ) return abs(c - a);
	if( dot(a - b, c - b) <= 0.0 ) return abs(c - b);
	return abs(cross(b - a, c - a)) / abs(b - a);
}

bool contains(const vector<P> &plg, rP pt){
	int cnt = 0;
	double y = imag(pt);

	for(int i = 0; i < plg.size(); ++i){
		int j = (i + 1 == plg.size() ? 0: i + 1);

		if( distance_ls_p(plg[i], plg[j], pt) < EPS ){
			return false;
		}

		double dyi = imag(plg[i]) - y;
		double dyj = y - imag(plg[j]);
		double tx = (dyi * real(plg[j]) + dyj * real(plg[i])) / (dyi + dyj);

		if(imag(plg[i]) >= y && imag(plg[j]) < y){
			if( tx < real(pt) ) ++cnt;
		}
		else if(imag(plg[i]) < y && imag(plg[j]) >= y){
			if( tx < real(pt) ) ++cnt;
		}
	}

	return (cnt % 2 != 0);
}

P intersect(rP pa1, rP pa2, rP pb1, rP pb2){
	P da12 = pa2 - pa1;
	P db21 = pb1 - pb2;
	P dab1 = pb1 - pa1;
	double D = cross(da12, db21);
	double t = cross(dab1, db21) / D;
	return pa1 + t * da12;
}


void dfs(int now, rP prev, int S, double len, double sum){
	if(now == 1){
		ans = min(ans, sum);
		return;
	}

	vector<P> tri(3);

	for(int i = 1; i < pnts.size(); ++i){
		if(S >> i & 1){ continue; }
		if(abs(cross(pnts[now], pnts[i])) < EPS){
			continue;
		}

		int T = S | 1 << i;
		double nl = len;
		P base = prev;
		P pos = pnts[now];

		while(1){
			int idx = -1;
			double minarg = 9.9;
			double maxnorm = -1.0;

			tri[0] = base;
			tri[1] = pos;
			tri[2] = pnts[i];
			for(int j = 2; j < pnts.size(); ++j){
				if(!contains(tri, pnts[j])){
					bool cntn = false;
					for(int k = 0; k < 3; ++k){
						if(norm(pnts[j] - tri[k]) < EPS){
							cntn = true;
							break;
						}
					}
					if(cntn){
						continue;
					}

					double d1 = abs(pnts[j] - base), d2 = abs(pnts[j] - pnts[i]);
					double d3 = abs(pnts[i] - base);
					if(abs(d1 + d2 - d3) > EPS){
						continue;
					}
				}
				double a = abs(arg((pnts[j] - base) / (pos - base)));
				double nm = norm(pnts[j] - base);
				if(a + EPS < minarg){
					minarg = a;
					maxnorm = nm;
					idx = j;
				}
				else if(abs(a - minarg) < EPS && maxnorm < nm){
					minarg = a;
					maxnorm = nm;
					idx = j;
				}
			}

			if(idx == -1) break;

			pos = intersect(pos, pnts[i], base, pnts[idx]);
			nl -= abs(pnts[idx] - base);
			base = pnts[idx];
			T |= idx;
		}

		if(nl > abs(pnts[1] - base) - EPS){
			dfs(i, base, T, nl, sum + abs(pnts[now] - pnts[i]));
		}
	}
}


int main(){
	int n, x, y;
	while(scanf("%d", &n), n){
		pnts.resize(n + 2);
		for(int i = 0; i < n + 2; ++i){
			scanf("%d%d", &x, &y);
			pnts[i] = P(x, y);
		}

		if(norm(pnts[0]) < norm(pnts[1])){
			puts("-1");
		}
		else{
			ans = abs(pnts[0]) + abs(pnts[1]);
			dfs(0, P(), 1, abs(pnts[0]), 0.0);
			printf("%f\n", ans);
		}
	}
}
accuracy: 0.25
time_ms: 410
memory_kb: 1172
final_rank: 14

code_snippet: #include <cstdio>
#include <vector>
#include <algorithm>
#include <utility>
#include <complex>
#include <cmath>
using namespace std;

typedef complex<double> P;
typedef const P &rP;

#define EPS 1e-7

double ans;
vector<P> pnts;

double dot(rP va, rP vb){
	return real(va) * real(vb) + imag(va) * imag(vb);
}

double cross(rP a, rP b){
	return real(a) * imag(b) - imag(a) * real(b);
}

double distance_ls_p(rP a, rP b, rP c){
	if( dot(b - a, c - a) <= 0.0 ) return abs(c - a);
	if( dot(a - b, c - b) <= 0.0 ) return abs(c - b);
	return abs(cross(b - a, c - a)) / abs(b - a);
}

bool contains_tri(const vector<P> &plg, rP pt){
	int cnt = 0;
	double y = imag(pt);

	for(int i = 0; i < 3; ++i){
		int j = (i == 2 ? 0: i + 1);

		if( distance_ls_p(plg[i], plg[j], pt) < EPS ){
			return (i == 2);
		}

		double dyi = imag(plg[i]) - y;
		double dyj = y - imag(plg[j]);
		double tx = (dyi * real(plg[j]) + dyj * real(plg[i])) / (dyi + dyj);

		if(imag(plg[i]) >= y && imag(plg[j]) < y){
			if( tx < real(pt) ) ++cnt;
		}
		else if(imag(plg[i]) < y && imag(plg[j]) >= y){
			if( tx < real(pt) ) ++cnt;
		}
	}

	return (cnt % 2 != 0);
}

P intersect(rP pa1, rP pa2, rP pb1, rP pb2){
	P da12 = pa2 - pa1;
	P db21 = pb1 - pb2;
	P dab1 = pb1 - pa1;
	double D = cross(da12, db21);
	double t = cross(dab1, db21) / D;
	return pa1 + t * da12;
}


void dfs(int now, rP prev, int S, double len, double sum){
	if(now == 1){
		ans = min(ans, sum);
		return;
	}

	vector<P> tri(3);

	for(int i = 1; i < pnts.size(); ++i){
		if(S >> i & 1){ continue; }
		if(abs(cross(pnts[now], pnts[i])) < EPS){
			continue;
		}

		int T = S | 1 << i;
		double nl = len;
		P base = prev;
		P pos = pnts[now];

		while(1){
			int idx = -1;
			double minarg = 9.9;
			double maxnorm = -1.0;

			tri[0] = base;
			tri[1] = pos;
			tri[2] = pnts[i];
			for(int j = 2; j < pnts.size(); ++j){
				if(!contains_tri(tri, pnts[j])){ continue; }
				double a = abs(arg((pnts[j] - base) / (pos - base)));
				double nm = norm(pnts[j] - base);
				if(a + EPS < minarg){
					minarg = a;
					maxnorm = nm;
					idx = j;
				}
				else if(abs(a - minarg) < EPS && maxnorm < nm){
					minarg = a;
					maxnorm = nm;
					idx = j;
				}
			}

			if(idx == -1) break;

			pos = intersect(pos, pnts[i], base, pnts[idx]);
			nl -= abs(pnts[idx] - base);
			base = pnts[idx];
			T |= idx;
		}

		if(nl > abs(pnts[1] - base) - EPS){
			dfs(i, base, T, nl, sum + abs(pnts[now] - pnts[i]));
		}
	}
}


int main(){
	int n, x, y;
	while(scanf("%d", &n), n){
		pnts.resize(n + 2);
		for(int i = 0; i < n + 2; ++i){
			scanf("%d%d", &x, &y);
			pnts[i] = P(x, y);
		}

		if(norm(pnts[0]) < norm(pnts[1])){
			puts("-1");
		}
		else{
			ans = abs(pnts[0]) + abs(pnts[1]);
			dfs(0, P(), 1, abs(pnts[0]), 0.0);
			printf("%f\n", ans);
		}
	}
}
accuracy: 0.25
time_ms: 220
memory_kb: 1172
final_rank: 13

code_snippet: #include<stdio.h>
#include<math.h>
#include<vector>
#include<string.h>

int n;
int xs[10],ys[10];
int fx,fy;
double ans,maxLen;

std::vector<int> getInDeltaPoints(int bx,int by,int dx,int dy,int nx,int ny){
	std::vector<int> re;
	int vxs[3],vys[3],dxs[3],dys[3];
	vxs[0]=dx-bx;
	vys[0]=dy-by;
	vxs[1]=nx-dx;
	vys[1]=ny-dy;
	vxs[2]=bx-nx;
	vys[2]=by-ny;
	
	for(int i=0;i<=n;i++){
		int p=0,m=0,zero=0;
		dxs[0]=xs[i]-bx;
		dys[0]=ys[i]-by;
		dxs[1]=xs[i]-dx;
		dys[1]=ys[i]-dy;
		dxs[2]=xs[i]-nx;
		dys[2]=ys[i]-ny;
		for(int j=0;j<3;j++){
			if(dxs[j]==0&&dys[j]==0)continue;
			int g=vxs[j]*dys[j]-dxs[j]*vys[j];
			if(g==0){
				zero++;
			}else if(g<0){
				m++;
			}else{
				p++;
			}
		}
		if(p==3||m==3)re.push_back(i);
		if(zero==1&&(p==2||m==2))re.push_back(i);
	}
	return re;
}

void saiki(int bx,int by,int dx,int dy,int spents[10],double RopeLen,double moveLen);

void saiki2(int bx,int by,int dx,int dy,int gx,int gy,std::vector<int>& perm,int spents[10],double RopeLen,double moveLen){
	if(RopeLen>maxLen)return;
	if(ans!=-1&&ans<moveLen)return ;
	if(getInDeltaPoints(bx,by,dx,dy,gx,gy).empty()==true){
		double lastAdd=sqrt((bx-gx)*(bx-gx)+(by-gy)*(by-gy));
		if(RopeLen+lastAdd>maxLen)return;
		moveLen+=sqrt((dx-gx)*(dx-gx)+(dy-gy)*(dy-gy));
		if(gx==fx&&gy==fy){
			if(ans==-1||ans>moveLen)ans=moveLen;
		}else{
			saiki(bx,by,gx,gy,spents,RopeLen,moveLen);
		}
		return ;
	}
	for(unsigned int i=0;i<perm.size();i++){
		int no=perm[i];
		if(spents[no]==0&&getInDeltaPoints(bx,by,dx,dy,xs[no],ys[no]).empty()==true){
			spents[no]=1;
			double t=sqrt((bx-xs[no])*(bx-xs[no])+(by-ys[no])*(by-ys[no]));
			saiki2(xs[no],ys[no],dx,dy,gx,gy,perm,spents,RopeLen+t,moveLen);
			spents[no]=0;
		}
	}
}

void saiki(int bx,int by,int dx,int dy,int spents[10],double RopeLen,double moveLen){
	std::vector<int> perm=getInDeltaPoints(bx,by,dx,dy,fx,fy);
	saiki2(bx,by,dx,dy,fx,fy,perm,spents,RopeLen,moveLen);
	for(int i=0;i<=n;i++){
		if(spents[i]==0){
			spents[i]=1;
			perm=getInDeltaPoints(bx,by,dx,dy,xs[i],ys[i]);
			saiki2(bx,by,dx,dy,xs[i],ys[i],perm,spents,RopeLen,moveLen);
			spents[i]=0;
		}
	}
}

void calc(){
	int dx,dy;
	scanf("%d %d %d %d",&dx,&dy,&fx,&fy);
	for(int i=0;i<n;i++)scanf("%d %d",&xs[i],&ys[i]);
	xs[n]=0;
	ys[n]=0;
	int spents[10]={0};
	ans=-1;
	maxLen=sqrt(dx*dx+dy*dy);
	saiki(0,0,dx,dy,spents,0,0);
	if(ans==-1){
		printf("-1\n");
	}else{
		printf("%.7lf\n",ans);
	}
}

int main(){
	while(1){
		scanf("%d",&n);
		if(n==0)break;
		calc();
	}
}
accuracy: 1
time_ms: 60
memory_kb: 1096
final_rank: 3

code_snippet: #include <iostream>
#include <cmath>
#include <vector>
#include <complex>
#include <cassert>
#include <algorithm>
using namespace std;

typedef complex<double> point;

struct line : public vector<point> {
	line(const point& a, const point& b) { push_back(a); push_back(b); }
};

const double pi  = M_PI;
const double inf = 1e10;
const double eps = 1e-10;
point  unit (const point& v)                 { return v/abs(v);     }
point  ortho(const point& v)                 { return v*point(0,1); }
point  vec  (const line&  l)                 { return l[1]-l[0];    }
bool   equal(const double a, const double b) { return abs(a-b)<eps; }
bool   equal(const point& a, const point& b) { return abs(a-b)<eps; }
double dot  (const point& a, const point& b) { return (a*conj(b)).real(); }
double cross(const point& a, const point& b) { return (conj(a)*b).imag(); }

int ccw(const point& a, const point& b, const point& c) {
	point u=b-a, v=c-a;
	if(cross(u,v) > 0 ) return +1; // ccw
	if(cross(u,v) < 0 ) return -1; // cw
	if(  dot(u,v) < 0 ) return +2; // cab
	if(abs(u) < abs(v)) return -2; // abc
	return 0;                      // acb
}

int ccw(const line& s, const point& p) {
	return ccw(s[0], s[1], p);
}

point crosspoint(const line& l, const line& m) {
	double A = cross(vec(l), vec(m));
	double B = cross(vec(l), l[1]-m[0]);
	if(abs(A)<eps) {			// parallel
		assert(abs(B)<eps);
		return m[1];			// sameline
	}
	return m[0] + B/A*vec(m);
}

bool contain(const point& a, const point& b, const point& c, const point& p) {
	return (ccw(a,b,p)!=-1 && ccw(b,c,p)!=-1 && ccw(c,a,p)!=-1)
	    || (ccw(a,b,p)!=+1 && ccw(b,c,p)!=+1 && ccw(c,a,p)!=+1);
}

int N;
point pile[8],dog,food;

pair<double,point> check(point base, point curr, point dest, double rest) {
	//cout << base << curr << dest << rest << endl;
	int mi=-1;
	double md=0,ma=inf;
	for(int i=0; i<N; i++) {
		if(equal(pile[i],base)) continue;
		if(equal(pile[i],curr)) continue;
		if(equal(pile[i],dest)) continue;
		if(equal(base,curr)) continue;
		if(equal(curr,dest)) continue;
		if(equal(dest,base)) continue;
		if(!contain(base,curr,dest,pile[i])) continue;
		double d = abs(pile[i]-base);
		double a = abs(arg(curr-base)-arg(pile[i]-base));
		if(equal(a,ma)) {
			if(md<d) { mi=i; md=d; ma=a; }
		}
		else if(a<ma) {
			mi=i; md=d; ma=a;
		}
	}

	if(mi<0) return make_pair(rest,base);

	line l(base, pile[mi]);
	line m(curr, dest);
	curr = crosspoint(l,m);
	return check(pile[mi], curr, dest, rest-abs(pile[mi]-base));;
}

double solve(int use, point base, point curr, double rest, double dist) {
	pair<double,point> ret = check(base,curr,food,rest);
	if(ret.first >= abs(ret.second-food)) return dist + abs(food-curr);
	double ans=inf;
	for(int i=0; i<N; i++) {
		if(use&(1<<i)) continue;
		ret = check(base,curr,pile[i],rest);
		if(ret.first < 0) continue;
		ans=min(ans,solve(use|(1<<i), ret.second, pile[i], ret.first, dist+abs(pile[i]-curr)));
	}
	return ans;
}

int main()
{
	while(cin>>N, N)
	{
		cin >> dog.real() >> dog.imag();
		cin >> food.real() >> food.imag();
		for(int i=0; i<N; i++) {
			cin >> pile[i].real() >> pile[i].imag();
		}
		cout.setf(ios::fixed); cout.precision(10);
		double ans = solve(0, 0, dog, abs(dog), 0);
		if(ans==inf) cout << "-1" << endl;
		else cout << ans << endl;
	}		
}
accuracy: 1
time_ms: 3670
memory_kb: 1028
final_rank: 9

code_snippet: #include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <climits>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1<<29;
const double PI = acos(-1);
const double EPS = 1e-8;

typedef complex<double> P;
namespace std {
  bool operator < (const P& a, const P& b) {
    // if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() {}
};
int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > 0)   return +1;       // counter clockwise
  if (cross(b, c) < 0)   return -1;       // clockwise
  if (dot(b, c) < 0)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}
typedef vector<P> G;
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
// 点-凸多角形包含関係
bool convex_contain(const G &g, const P &p) { // 半時計回りを仮定
  REP(i,g.size())
    if (ccw(g[i], next(g, i), p) == -1) return 0;
  return 1;
}
// 角度関連
double angle(const P &a, const P &b) {        // ベクトルａからみたベクトルｂの角度の計算[0,2pi]
  double ret = arg(b)-arg(a);
  return (ret>=0) ? ret : ret + 2*PI;
}
double angle2(const P &a, const P &b) { // ベクトルaとベクトルbの間の角度
  return min(angle(a,b), angle(b,a));
}
P rotate(P p, double ang) {
  return p * P(cos(ang), sin(ang));
}


P p[10];
P dog;
int n;

typedef pair<double,double> pdd;
// centerに繋がれているとき、dからp[nxt]まで行くために巻きつく紐と総移動距離
pdd func(int &center, const P &d, int nxt) {
  //cout << "func(" << p[center] << ", " << d << ", " << p[nxt] << ")" << endl;
  L l(d, p[nxt]);
  int cw = ccw(p[center], d, p[nxt]);
  if (abs(cw) != 1) {           // ikeru
    return pdd(0, abs(p[nxt]-d));
  }
  G g(3);
  g[0] = p[center];
  g[1] = d;
  g[2] = p[nxt];
  if (cw == -1) swap(g[1],g[2]);
  double minang = INF;
  int id = -1;
  REP(i,n+1) {
    if (convex_contain(g, p[i])) {
      if (i == nxt || i == center || abs(p[i]-d) < EPS) continue;
      double ang = angle2(d-p[center], p[i]-p[center]);
      if (minang > ang){
        minang = ang;
        id = i;
      }
    }
  }
  if (id == -1) {
    // ikeru
    return pdd(0, abs(p[nxt]-d));
  }
  pdd res = pdd(abs(p[id]-p[center]), 0);
  center = id;
  pdd ret = func(center, d, nxt);
  return pdd(res.first + ret.first, res.second + ret.second);
}

double ans;

double simulate(vector<int> v) {
  double sum = 0;
  int center = n;
  P now = dog;
  double res = 0;
  v.push_back(9);
  REP(i,v.size()) {
    pdd ret = func(center, now, v[i]);
    sum += ret.first;
    res += ret.second;
    // cout << sum << " " << res << endl;
    now = p[v[i]];
    if (sum+abs(p[center]-p[9]) > abs(dog) + EPS) return INF;
    if (res > ans) return INF;
  }
  sum += abs(p[center] - now);
  // FOR(it, v) cout << *it << " ";cout << endl;
  // cout << sum << ", " << res << endl;
  if (sum > abs(dog)+EPS) return INF;
  // if (res < 220) {
  //   FOR(it, v) cout << *it << " "; cout << endl;
  //   cout << p[center] << " " << now << endl;
  //   cout << sum << " " << res << endl;
  // }
  else return res;
}

vector<int> v;
void solve(int S) {
  ans = min(ans, simulate(v));
  if (S==(1<<n)-1) return;
  REP(i,n) {
    if (!(S>>i&1)) {
      v.push_back(i);
      solve(S|1<<i);
      v.pop_back();
    }
  }
}

int main() {
  while(cin>>n,n) {
    cin >> dog.real() >> dog.imag();
    cin >> p[9].real() >> p[9].imag();
    REP(i,n) cin >> p[i].real() >> p[i].imag();
    p[n] = P(0,0);
    // vector<int> v(2);v[0]=0;v[1]=5;
    // simulate(v);return 0;
    ans = simulate(vector<int>(1,n));
    solve(0);
    if (ans >= INF-EPS) {
      cout << -1 << endl;
    } else {
      printf("%.10f\n", ans);
    }
  }
}
accuracy: 1
time_ms: 6440
memory_kb: 1032
final_rank: 11

code_snippet: #include<cmath>
#include<cstdio>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const double EPS=1e-7;
const double INF=1e77;
const double PI=acos(-1);

template<class T>
struct point{
	T x,y;
	point &operator+=(const point &a){ x+=a.x; y+=a.y; }
	point &operator-=(const point &a){ x-=a.x; y-=a.y; }
	point operator+(const point &a)const{ return (point){x+a.x,y+a.y}; }
	point operator-(const point &a)const{ return (point){x-a.x,y-a.y}; }
};

template<class T>
point<T> operator*(T c,const point<T> &a){ return (point<T>){c*a.x,c*a.y}; }

bool operator==(const point<double> &a,const point<double> &b){
	return abs(a.x-b.x)<EPS && abs(a.y-b.y)<EPS;
}
bool operator!=(const point<double> &a,const point<double> &b){
	return abs(a.x-b.x)>EPS || abs(a.y-b.y)>EPS;
}

template<class T>
T cross(const point<T> &a,const point<T> &b){ return a.x*b.y-a.y*b.x; }

template<class T>
double arg(const point<T> &a){
	double t=atan2(a.y,a.x);
	return t<0?t+2*PI:t;
}

template<class T>
struct line{
	point<T> a,b;
	operator line<double>()const{ return (line<double>){a,b}; }
};

enum {CCW=1,CW=-1,ON=0};
int ccw(const point<double> &a,const point<double> &b,const point<double> &c){
	double rdir=cross(b-a,c-a);
	if(rdir> EPS) return CCW;
	if(rdir<-EPS) return CW;
	return ON;
}

template<class T>
double dist(const point<T> &a,const point<T> &b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

template<class T>
bool cover(const point<T> &a,const point<T> &b,const point<T> &c,const point<T> &p){
	int d1=ccw(p,a,b);
	int d2=ccw(p,b,c);
	int d3=ccw(p,c,a);
	return !(d1==CCW && d2== CW || d1==CCW && d3== CW || d2==CCW && d3== CW
		  || d1== CW && d2==CCW || d1== CW && d3==CCW || d2== CW && d3==CCW);
}

point<double> get_intersect(const line<double> &L1,const line<double> &L2){
	double a1=cross(L1.b-L1.a,L2.b-L2.a);
	double a2=cross(L1.b-L1.a,L1.b-L2.a);
	if(abs(a1)<EPS) return L1.a;
	return L2.a+a2/a1*(L2.b-L2.a);
}

int n;
point<double> p[9]; // ツ杭, ツつスツつセツつオ p[n] ツづ債ゴツーツδ?

bool vis[9];
double dfs(point<double> D,point<double> O,double r){ // ツ個「ツづ個暗環置, ツ嘉アツ転ツ陳?心, ツ紐ツづ個陳キツつウ
	if(D==p[n]) return 0;

	if(r+EPS<dist(O,p[n])) return INF;

	double res=INF;
	rep(i,n+1) if(!vis[i]) {
		// D ツつゥツづァ P ツづ可古シツつゥツづ?づ?づ慊づ?つキツつョツ進ツづ?
		point<double> P=p[i];
		double t0=arg(D-O);

		int j0=-1; // ツづ債つカツづ淞づ可づ板づつつゥツづゥツ杭ツづーツ個ゥツづつつッツづゥ
		rep(j,n) if(p[j]!=O && p[j]!=P && p[j]!=D) {
			if(cover(O,D,P,p[j])){ // ツ三ツ角ツ形 ODP ツづ個陳?づ可杭 j ツつェツつ?づゥツづ?つォ
				if(j0==-1) j0=j;
				else{
					double t1=arg(p[j0]-O)-t0; t1=min(abs(t1),abs(2*PI-t1));
					double t2=arg(p[j ]-O)-t0; t2=min(abs(t2),abs(2*PI-t2));
					if(t2+EPS<t1 || abs(t1-t2)<EPS && dist(p[j0],O)<dist(p[j],O)){
						j0=j;
					}
				}
			}
		}
		if(j0==-1){ // ツづ?づ個杭ツづ可づ?づ板づつつゥツづァツづ按つ「
			double d=dist(O,P);
			if(d<r+EPS){
				vis[i]=true;
				res=min(res,dist(D,P)+dfs(P,O,r));
				vis[i]=false;
			}
		}
		else{ // ツ杭 j0 ツづ可づ板づつつゥツづゥ
			point<double> Q=get_intersect((line<double>){D,P},(line<double>){O,p[j0]});
			double d=dist(O,Q);
			if(d<r+EPS){
				res=min(res,dist(D,Q)+dfs(Q,p[j0],r-dist(O,p[j0])));
			}
		}
	}

	return res;
}

int main(){
	for(;scanf("%d",&n),n;){
		point<double> D; // dog
		scanf("%lf%lf%lf%lf",&D.x,&D.y,&p[n].x,&p[n].y);
		rep(i,n) scanf("%lf%lf",&p[i].x,&p[i].y);

		point<double> O={0,0};
		double ans=dfs(D,O,dist(D,O));
		printf("%.9f\n",ans<INF/2?ans:-1);
	}

	return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 824
final_rank: 2

code_snippet: #include<cmath>
#include<cstdio>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const double EPS=1e-7;
const double INF=1e77;
const double PI=acos(-1);

template<class T>
struct point{
	T x,y;
	point &operator+=(const point &a){ x+=a.x; y+=a.y; }
	point &operator-=(const point &a){ x-=a.x; y-=a.y; }
	point operator+(const point &a)const{ return (point){x+a.x,y+a.y}; }
	point operator-(const point &a)const{ return (point){x-a.x,y-a.y}; }
};

template<class T>
point<T> operator*(T c,const point<T> &a){ return (point<T>){c*a.x,c*a.y}; }

bool operator==(const point<double> &a,const point<double> &b){
	return abs(a.x-b.x)<EPS && abs(a.y-b.y)<EPS;
}
bool operator!=(const point<double> &a,const point<double> &b){
	return abs(a.x-b.x)>EPS || abs(a.y-b.y)>EPS;
}

template<class T>
T cross(const point<T> &a,const point<T> &b){ return a.x*b.y-a.y*b.x; }

template<class T>
double arg(const point<T> &a){
	double t=atan2(a.y,a.x);
	return t<0?t+2*PI:t;
}

template<class T>
struct line{
	point<T> a,b;
	operator line<double>()const{ return (line<double>){a,b}; }
};

enum {CCW=1,CW=-1,ON=0};
int ccw(const point<double> &a,const point<double> &b,const point<double> &c){
	double rdir=cross(b-a,c-a);
	if(rdir> EPS) return CCW;
	if(rdir<-EPS) return CW;
	return ON;
}

template<class T>
double dist(const point<T> &a,const point<T> &b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

template<class T>
bool cover(const point<T> &a,const point<T> &b,const point<T> &c,const point<T> &p){
	int d1=ccw(p,a,b);
	int d2=ccw(p,b,c);
	int d3=ccw(p,c,a);
	return !(d1==CCW && d2== CW || d1==CCW && d3== CW || d2==CCW && d3== CW
		  || d1== CW && d2==CCW || d1== CW && d3==CCW || d2== CW && d3==CCW);
}

point<double> get_intersect(const line<double> &L1,const line<double> &L2){
	double a1=cross(L1.b-L1.a,L2.b-L2.a);
	double a2=cross(L1.b-L1.a,L1.b-L2.a);
	if(abs(a1)<EPS) return L1.a;
	return L2.a+a2/a1*(L2.b-L2.a);
}

int n;
point<double> p[9]; // ツ杭, ツつスツつセツつオ p[n] ツづ債ゴツーツδ?

bool vis[9];
double dfs(point<double> D,point<double> O,double r){ // ツ個「ツづ個暗環置, ツ嘉アツ転ツ陳?心, ツ紐ツづ個陳キツつウ
	if(D==p[n]) return 0;

	if(r+EPS<dist(O,p[n])) return INF;
// printf("D = (%.2f, %.2f)\n",D.x,D.y);
// printf("O = (%.2f, %.2f)\n",O.x,O.y);
// printf("r = %.2f\n",r);
	double res=INF;
	rep(i,n+1) if(!vis[i]) {
		// D ツつゥツづァ P ツづ可古シツつゥツづ?づ?づ慊づ?つキツつョツ進ツづ?
		point<double> P=p[i];
		double t0=arg(D-O);

		if(ccw(O,D,P)!=ON){ // O, D, P ツつェツ暗ェツ陳シツ静シツ湘」ツづ可づ按つ「ツづ?つォ
			int j0=-1; // ツづ債つカツづ淞づ可づ板づつつゥツづゥツ杭ツづーツ個ゥツづつつッツづゥ
			rep(j,n) if(p[j]!=O && p[j]!=P && p[j]!=D) {
				if(cover(O,D,P,p[j])){ // ツ三ツ角ツ形 ODP ツづ個陳?づ可杭 j ツつェツつ?づゥツづ?つォ
					if(j0==-1) j0=j;
					else{
						double t1=arg(p[j0]-O)-t0; t1=min(abs(t1),abs(2*PI-t1));
						double t2=arg(p[j ]-O)-t0; t2=min(abs(t2),abs(2*PI-t2));
						if(t2+EPS<t1 || abs(t1-t2)<EPS && dist(p[j0],O)<dist(p[j],O)){
							j0=j;
						}
					}
				}
			}
			if(j0==-1){ // ツづ?づ個杭ツづ可づ?づ板づつつゥツづァツづ按つ「
				double d=dist(O,P);
				if(d<r+EPS){
					vis[i]=true;
					res=min(res,dist(D,P)+dfs(P,O,r));
					vis[i]=false;
				}
			}
			else{ // ツ杭 j0 ツづ可づ板づつつゥツづゥ
				point<double> Q=get_intersect((line<double>){D,P},(line<double>){O,p[j0]});
				double d=dist(O,Q);
				if(d<r+EPS){
					res=min(res,dist(D,Q)+dfs(Q,p[j0],r-dist(O,p[j0])));
				}
			}
		}
		else{ // O, D, P ツつェツ暗ェツ陳シツ静シツ湘」ツづ可つ?づゥツづ?つォ
		}
	}

	return res;
}

int main(){
	for(;scanf("%d",&n),n;){
		point<double> D; // dog
		scanf("%lf%lf%lf%lf",&D.x,&D.y,&p[n].x,&p[n].y);
		rep(i,n) scanf("%lf%lf",&p[i].x,&p[i].y);

		point<double> O={0,0};
		double ans=dfs(D,O,dist(D,O));
		printf("%.9f\n",ans<INF/2?ans:-1);
	}

	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 824
final_rank: 1