Problem:
Kuru Kuru Door
くるくるドア
ACM (Automatic Cleaning Machine) 社が2011年に開発した全自動円形掃除機 ICPC (Intelligent Circular Perfect Cleaner) は，
日中に自動で動き出し，自分が通り過ぎた場所のゴミを掃除する機能を備えている．
加えて，この ICPC は，バッテリー残量が低下した場合に自動的に電源の位置まで戻る機能も備えている．
この度，JAG (Japan Alumni Group) と名乗る謎の組織から， ACM 社に対し大量の ICPC の発注があった．
しかし，その発注には条件が付いていた．
それは，彼らが本拠地としているビルの内部にある「くるくるドア」に ICPC を対応させることである．
くるくるドアは，以下に述べるように平面上の物体としてモデル化されている．
くるくるドアは，原点で接続された長さ
R
の 2
n
(≥ 4) 枚のドアの組として表される．
これらのドアは，角度 π/
n
おきに並んでいる．
くるくるドアは手動であり，ドアのどこに触れても触れた方向( ICPC との重なりが解消される方向)へ原点中心に一斉に回転させることができるが，
平行移動させることはできない．
初期状態では，ドアのちょうど2枚が
y
軸に平行である．
また，原点を中心とする半径
R
の円のうち，
y
座標の絶対値が
R
sin(π/(2
n
)) 以上である部分および，
y
軸上で
y
座標の絶対値が
R
以上の部分は壁になっている．
これらの壁は押すことができない．
平面上で ICPC は半径
r
の円として表される．
 ICPC の電源は点
T
= (
x
t
,
y
t
) にあり， ICPC はその中心座標が電源の位置に重なっている時バッテリーを充電することができる．
はじめに ICPC の中心座標が点
S
= (
x
s
,
y
s
) となる位置にあるとき，
電源の位置まで ICPC が最短経路を通って戻れるようにすることが， JAG から出された ICPC 発注の条件である．
なお， ICPC がくるくるドアに対して正確な挙動を行うことを確かめるために， ICPC の初期位置と電源の位置は，くるくるドアを挟んで反対側となるように与えられる．
 ACM 社は，凄腕プログラマーのあなたに，くるくるドアの寸法， ICPC の中心座標
S
と半径，電源の位置
T
が与えられたとき，ICPCが電源の位置へ到達できるかを判定し，到達可能な場合は ICPC の中心座標が移動する最短経路の長さを求めるプログラムの作成を依頼した．
Input
入力は，複数のデータセットから構成され，1つの入力に含まれるデータセットの数は60個以下である．
各データセットの形式は次の通りである．
n
r
R
x
s
y
s
x
t
y
t
n
はくるくるドアを構成するドアの枚数の半分を表す整数であり，2 ≤
n
≤ 10 と仮定して良い．
r
，
R
はそれぞれ ICPC の半径，くるくるドアの一枚あたりの長さを表す整数であり，1以上10以下と仮定して良い．
(
x
s
,
y
s
) は ICPC の初期位置の中心座標，(
x
t
,
y
t
) は電源の位置を表す．
x
s
，
y
s
，
x
t
，
y
t
はそれぞれ整数であり，-1,000 ≤
x
s
≤ -
r
- 1， -1,000 ≤
y
s
≤ 1,000，
r
+ 1 ≤
x
t
≤ 1,000， -1,000 ≤
y
t
≤ 1,000 を満たすと仮定して良い．
加えて，点 (
x
s
,
y
s
)， (
x
t
,
y
t
) はそれぞれ原点から距離
R
+
r
+ 10
-6
以上離れていると仮定して良い．
すなわち， ICPC と電源は初期状態でいずれもくるくるドアの外側にあり，互いにくるくるドアを挟んで反対側に位置している．
また，
r
および
R
が 10
-6
だけ変化しても， ICPC の電源位置への到達可能性は変わらないと仮定して良い．
入力の終わりは1つのゼロだけからなる行で示される．
下図は後に示す Sample Input 中の最初のデータセットにおける， ICPC の初期位置
S
，電源位置
T
，くるくるドアおよび壁の配置を表している．
Output
各データセットについて， ICPC が電源の位置に到達できる場合は，電源の位置までの移動距離の最小値を1行に出力せよ．
この場合，出力の絶対誤差は 10
-6
以内でなくてはならない．
到達できない場合は，-1 を1行に出力せよ．
Sample Input
3
1 4
-5 5
5 -5
10
1 10
-10 5
5 -10
5
3 5
-20 0
20 0
8
1 9
-14 58
6 24
2
2 8
-57 -113
42 -31
4
1 4
-4 -5
4 5
0
Output for Sample Input
17.5032106371
41.3850388846
-1
102.0656847372
178.1399151364
19.5548716821

Submitted solutions:

code_snippet: /*	author:  Kite_kuma
	created: 2021.11.01 22:38:19 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region geometry_light

using Real = long double;
using R = Real;
using Point = std::complex<Real>;
using Vec = Point;
const Real EPS = 1e-10, PI = acos(-1);

inline bool eq(const Real &a, const Real &b) { return fabs(b - a) < EPS; }
inline bool eq(const Point &a, const Point &b) { return fabs(b - a) < EPS; }
/*
	-1: a < b
	0 : a == b
	1 : a > b
*/
inline int compare(const Real &a, const Real &b) { return eq(a, b) ? 0 : a < b ? -1 : 1; }
inline int sign(const Real &a) { return fabs(a) < EPS ? 0 : a < 0 ? -1 : 1; }

namespace std {
const Point operator*(const Point &p, const Real &d) { return Point(real(p) * d, imag(p) * d); }
}  // namespace std

std::istream &operator>>(std::istream &is, Point &p) {
	Real a, b;
	is >> a >> b;
	p = Point(a, b);
	return is;
}
std::ostream &operator<<(std::ostream &os, Point &p) { return os << std::fixed << std::setprecision(10) << p.real() << " " << p.imag(); }

// rotate point 'p' for counter clockwise direction
const Point rotate(const Real &theta, const Point &p) {
	return Point(cos(theta) * p.real() - sin(theta) * p.imag(), sin(theta) * p.real() + cos(theta) * p.imag());
}

const Real radian_to_degree(const Real &r) { return (r * 180.0 / PI); }

const Real degree_to_radian(const Real &d) { return (d * PI / 180.0); }

// get angle a-b-c (<pi)
const Real get_angle(const Point &a, const Point &b, const Point &c) {
	const Point v(a - b), w(c - b);
	Real theta = fabs(atan2(w.imag(), w.real()) - atan2(v.imag(), v.real()));
	return std::min(theta, 2 * PI - theta);
}

namespace std {
bool operator<(const Point &a, const Point &b) { return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag(); }
}  // namespace std

struct Line {
	Point a, b;

	Line() = default;

	Line(Point a, Point b) : a(a), b(b) {}

	Line(Real A, Real B, Real C)  // Ax + By = C
	{
		if(eq(A, 0))
			a = Point(0, C / B), b = Point(1, C / B);
		else if(eq(B, 0))
			b = Point(C / A, 0), b = Point(C / A, 1);
		else
			a = Point(0, C / B), b = Point(C / A, 0);
	}

	friend std::ostream &operator<<(std::ostream &os, Line &p) { return os << p.a << " -- " << p.b; }

	friend std::istream &operator>>(std::istream &is, Line &a) { return is >> a.a >> a.b; }
};

struct Segment : Line {
	Segment() = default;

	Segment(Point a, Point b) : Line(a, b) {}
};

struct Circle {
	Point p;
	Real r;

	Circle() = default;

	Circle(Point p, Real r) : p(p), r(r) {}
};

using Points = std::vector<Point>;
using Polygon = std::vector<Point>;
using Segments = std::vector<Segment>;
using Lines = std::vector<Line>;
using Circles = std::vector<Circle>;

const Real cross(const Point &a, const Point &b) { return real(a) * imag(b) - imag(a) * real(b); }
const Real dot(const Point &a, const Point &b) { return real(a) * real(b) + imag(a) * imag(b); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C
const int ccw(const Point &a, Point b, Point c) {
	b = b - a, c = c - a;
	if(cross(b, c) > EPS) return +1;		// "COUNTER_CLOCKWISE"
	if(cross(b, c) < -EPS) return -1;		// "CLOCKWISE"
	if(dot(b, c) < -EPS) return +2;			// "ONLINE_BACK"
	if(norm(b) + EPS < norm(c)) return -2;	// "ONLINE_FRONT"
	return 0;								// "ON_SEGMENT"
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool parallel(const Line &a, const Line &b) { return eq(cross(a.b - a.a, b.b - b.a), 0.0); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool orthogonal(const Line &a, const Line &b) { return eq(dot(a.a - a.b, b.a - b.b), 0.0); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_A
Point projection(const Line &l, const Point &p) {
	double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + (l.a - l.b) * t;
}

Point projection(const Segment &l, const Point &p) {
	double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + (l.a - l.b) * t;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_B
Point reflection(const Line &l, const Point &p) { return projection(l, p) * 2.0 - p; }

int intersect(const Line &l, const Point &p) { return int(abs(ccw(l.a, l.b, p)) != 1); }

int intersect(const Line &l, const Line &m) {
	if(intersect(l, m.a) && intersect(l, m.b)) return -1;
	return int(abs(cross(l.b - l.a, m.b - m.a)) > EPS);
}

int intersect(const Segment &s, const Point &p) { return int(ccw(s.a, s.b, p) == 0); }

int intersect(const Line &l, const Segment &s) {
	if(intersect(l, s.a) && intersect(l, s.b)) return -1;
	return cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < EPS;
}

Real distance(const Line &l, const Point &p);

int intersect(const Circle &c, const Line &l) {
	Real d = c.r - distance(l, c.p);
	return fabs(d) < EPS ? 1 : d > 0. ? 2 : 0;
}

int intersect(const Circle &c, const Point &p) { return int(abs(abs(p - c.p) - c.r) < EPS); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B
int intersect(const Segment &s, const Segment &t) {
	if(eq(s.a, s.b)) return intersect(t, s.a);
	if(intersect(Line(s), t.a) && intersect(Line(s), t.b) &&
	   std::max(std::min(s.a, s.b), std::min(t.a, t.b)) < std::min(std::max(s.a, s.b), std::max(t.a, t.b)))
		return -1;
	return int(ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0);
}

int intersect(const Circle &c, const Segment &l) {
	const Point h = projection(l, c.p);
	if(norm(h - c.p) - c.r * c.r > EPS) return 0;
	auto d1 = abs(c.p - l.a), d2 = abs(c.p - l.b);
	if(compare(d1, c.r) == -1 && compare(d2, c.r) == -1) return 0;
	if(d1 < c.r - EPS && d2 > c.r - EPS || d1 > c.r - EPS && d2 < c.r - EPS) return 1;
	return dot(l.a - h, l.b - h) < 0 ? 2 : 0;
}

Real distance(const Point &a, const Point &b);

int number_of_common_tangents(const Circle &c1, const Circle &c2) {
	Real r1 = std::min(c1.r, c2.r), r2 = std::max(c1.r, c2.r), d = distance(c1.p, c2.p);
	int com = compare(r1 + r2, d);
	return com == 1 ? compare(d + r1, r2) + 1 : 3 - com;
	// if(c1.r < c2.r) swap(c1, c2);
	// Real d = abs(c1.p - c2.p);
	// if(compare(c1.r + c2.r, d) == -1) return 4;
	// if(eq(c1.r + c2.r, d)) return 3;
	// if(compare(c1.r - c2.r, d) == -1) return 2;
	// return int(eq(c1.r - c2.r, d));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_A&lang=jp
int intersect(const Circle &c1, const Circle &c2) { return 2 - abs(2 - number_of_common_tangents(c1, c2)); }

Real distance(const Point &a, const Point &b) { return abs(a - b); }

Real distance(const Line &l, const Point &p) { return abs(p - projection(l, p)); }

Real distance(const Line &l, const Line &m) { return intersect(l, m) ? 0 : distance(l, m.a); }

Real distance(const Segment &s, const Point &p) {
	Point r = projection(s, p);
	return intersect(s, r) ? distance(r, p) : std::min(abs(s.a - p), abs(s.b - p));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_D
Real distance(const Segment &a, const Segment &b) {
	if(intersect(a, b)) return 0;
	return std::min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)});
}

Real distance(const Line &l, const Segment &s) {
	if(intersect(l, s)) return 0;
	return std::min(distance(l, s.a), distance(l, s.b));
}

Point crosspoint(const Line &l, const Line &m) {
	Real A = cross(l.b - l.a, m.b - m.a);
	Real B = cross(l.b - l.a, l.b - m.a);
	if(eq(abs(A), 0.0) && eq(abs(B), 0.0)) return m.a;
	return m.a + (m.b - m.a) * B / A;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_C
Point crosspoint(const Segment &l, const Segment &m) { return crosspoint(Line(l), Line(m)); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_D
std::pair<Point, Point> crosspoint(const Circle &c, const Line l) {
	Point pr = projection(l, c.p);
	if(eq(distance(l, c.p), c.r)) return {pr, pr};
	Vec v = (l.b - l.a) / abs(l.b - l.a) * sqrt(c.r * c.r - norm(pr - c.p));
	return make_pair(pr - v, pr + v);
	// Vec e = (l.b - l.a) / abs(l.b - l.a);
	// double base = sqrt(c.r * c.r - norm(pr - c.p));
	// return {pr - e * base, pr + e * base};
}

std::pair<Point, Point> crosspoint(const Circle &c, const Segment &l) {
	if(intersect(c, l) == 2) return crosspoint(c, Line(l.a, l.b));
	auto ret = crosspoint(c, Line(l.a, l.b));
	if(dot(l.a - ret.first, l.b - ret.first) < EPS)
		ret.second = ret.first;
	else
		ret.first = ret.second;
	return ret;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_E
std::pair<Point, Point> crosspoint(const Circle &c1, const Circle &c2) {
	Real d = abs(c1.p - c2.p);
	Real a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));  // cosine theorem
	Real t = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	Point p1 = c1.p + Point(cos(t + a) * c1.r, sin(t + a) * c1.r);
	Point p2 = c1.p + Point(cos(t - a) * c1.r, sin(t - a) * c1.r);
	return make_pair(p1, p2);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_F
// "点 p を通る円 c の接線"の接点2つ
std::pair<Point, Point> tangent(const Circle &c1, const Point &p2) {
	return crosspoint(c1, Circle(p2, sqrt(norm(c1.p - p2) - c1.r * c1.r)));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_G
// 円 c1, c2 の共通接線
Lines tangent(Circle c1, Circle c2) {
	Lines ret;
	if(c1.r < c2.r) std::swap(c1, c2);
	Real g = norm(c1.p - c2.p);
	if(eq(g, 0)) return ret;
	Vec u = (c2.p - c1.p) / Real(sqrt(g));
	Vec v = rotate(PI * 0.5, u);
	for(int s : {-1, 1}) {
		Real h = (c1.r + s * c2.r) / sqrt(g);
		if(eq(1 - h * h, 0)) {
			ret.emplace_back(c1.p + u * c1.r, c1.p + (u + v) * c1.r);
		} else if(1 - h * h > 0) {
			Point uu = u * h, vv = v * sqrt(1 - h * h);
			ret.emplace_back(c1.p + (uu + vv) * c1.r, c2.p - (uu + vv) * c2.r * s);
			ret.emplace_back(c1.p + (uu - vv) * c1.r, c2.p - (uu - vv) * c2.r * s);
		}
	}
	return ret;
}

#pragma endregion

std::vector<double> dijkstra(int n, vector<tuple<int, int, double>> es, int s) {
	vector<vector<pair<int, double>>> g(n);
	for(auto [u, v, c] : es) {
		g[u].emplace_back(v, c);
		g[v].emplace_back(u, c);
	}
	const double INF = 1e18;
	std::vector<double> dist(g.size(), INF);
	using P = std::pair<double, int>;
	std::priority_queue<P, std::vector<P>, std::greater<P>> que;
	dist[s] = 0;
	que.push(pll(0, s));
	while(!que.empty()) {
		P p = que.top();
		que.pop();
		int v = p.second;
		if(dist[v] < p.first) continue;
		for(auto [to, cost] : g[v]) {
			if(dist[to] > dist[v] + cost) {
				dist[to] = dist[v] + cost;
				que.push(P(dist[to], to));
			}
		}
	}
	return dist;
}

ld solve(int n) {
	R cleaner_radius, door_len;
	cin >> cleaner_radius >> door_len;
	Point s, t;
	std::cin >> s >> t;
	Points pts = {s, t};
	debug(n, cleaner_radius, door_len, s, t);
	R center_radius = cleaner_radius / (sin(pi / (2. * n)));
	R radius_large_circle = door_len + cleaner_radius;
	R radius_small_circle = door_len - cleaner_radius;
	if(radius_small_circle < center_radius) return -10;

	Point edge = polar(door_len, pi / (2. * n));
	if(distance(edge, Point(edge.real(), -edge.imag())) < 2 * cleaner_radius) return -10;
	Points edges;
	edges.emplace_back(-edge.real(), edge.imag());
	edges.emplace_back(-edge.real(), -edge.imag());
	edges.emplace_back(edge.real(), edge.imag());
	edges.emplace_back(edge.real(), -edge.imag());

	Circles cs;
	{
		Point O(0, 0);
		cs.emplace_back(O, radius_large_circle);
		cs.emplace_back(O, radius_small_circle);
		cs.emplace_back(O, center_radius);
		foa(p, edges) cs.emplace_back(p, cleaner_radius);
	}
	const int cssize = cs.size();

	auto arg_is_ok = [&](R ar) {
		return !(in_range(ar, -pi + pi / (2. * n), 0 - pi / (2. * n)) || in_range(ar, pi / (2. * n), pi - pi / (2. * n)));
	};

	const Line wall = Line(Point(0, 1), Point(0, -1));

	auto seg_is_valid = [&](const Segment &seg) {
		if(intersect(wall, seg)) {
			if(abs(crosspoint(wall, seg).imag()) > door_len) return false;
		}
		rep(csid, cssize) {
			const Circle &c = cs[csid];
			if(intersect(c, seg)) {
				if(intersect(c, Line(seg)) <= 1) continue;
				pair<Point, Point> crs = crosspoint(c, seg);
				if(eq(crs.first, crs.second) && (eq(crs.first, seg.a) || eq(crs.first, seg.b))) continue;
				if(csid < 2) {
					auto ok = [&seg, &arg_is_ok](Point p) { return arg_is_ok(arg(p)) || eq(p, seg.a) || eq(p, seg.b); };
					if(ok(crs.first) && ok(crs.second)) continue;
				}
				return false;
			}
		}
		debug(seg.a, seg.b);
		return true;
	};

	V<tuple<int, int, double>> path;

	if(seg_is_valid(Segment(s, t))) return distance(s, t);

	// rep(i, cssize) rep(j, i + 1, cssize) {
	rep(i, 2, cssize) rep(j, i + 1, cssize) {
		auto ts = tangent(cs[i], cs[j]);
		foa(ln, ts) {
			// Point a = crosspoint(cs[i], ln).first, b = crosspoint(cs[j], ln).first;
			// if(eq(a, b)) continue;
			// Segment seg(a, b);
			Segment seg(ln.a, ln.b);
			if(seg_is_valid(seg)) {
				if(i == 0) {
					debug(j);
					debug(cs[i].p, cs[i].r);
					debug(cs[j].p, cs[j].r);
					debug(seg.a, seg.b);
				}
				path.emplace_back(pts.size(), pts.size() + 1, distance(seg.a, seg.b));
				pts.push_back(seg.a);
				pts.push_back(seg.b);
			}
		}
	}

	rep(ptid, 2) {
		Point p = pts[ptid];
		rep(i, cssize) {
			auto tts = tangent(cs[i], p);
			V<Point> ts = {tts.first, tts.second};
			foa(pt, ts) {
				Segment seg(p, pt);
				if(seg_is_valid(seg)) {
					path.emplace_back(ptid, pts.size(), distance(seg.a, seg.b));
					pts.push_back(seg.b);
				}
			}
		}
	}

	edge = polar(radius_small_circle, pi / (2. * n));
	pts.emplace_back(-edge.real(), edge.imag());
	pts.emplace_back(-edge.real(), -edge.imag());
	pts.emplace_back(edge.real(), edge.imag());
	pts.emplace_back(edge.real(), -edge.imag());
	edge = polar(radius_large_circle, pi / (2. * n));
	pts.emplace_back(-edge.real(), edge.imag());
	pts.emplace_back(-edge.real(), -edge.imag());
	pts.emplace_back(edge.real(), edge.imag());
	pts.emplace_back(edge.real(), -edge.imag());
	const int ps = pts.size();

	rep(i, ps) rep(j, i + 1, ps) {
		Point g = pts[i], h = pts[j];
		rep(csid, cssize) {
			auto c = cs[csid];
			if(intersect(c, g) && intersect(c, h)) {
				if(csid == 0) {	 // large
					if(h.real() * g.real() < 0 || h.imag() * g.imag() < 0) continue;
				} else if(csid == 1) {	// small
					if(g.imag() * h.imag() < 0) continue;
				}
				R a = arg(g - c.p), b = arg(h - c.p);
				a -= b;
				while(a < 0) a += pi * 2;
				if(a > pi) a = pi * 2 - a;
				path.emplace_back(i, j, a * c.r);
				continue;
			}
		}
	}

	return dijkstra(ps, path, 0)[1];
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n;
	// cin >> n;
	while(cin >> n && n) {
		ld res = solve(n);
		if(res < 0 || res > INF / 1000)
			print(-1);
		else
			cout << res << dl;
	}

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4000
final_rank: 1

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

const double EPS = 1e-8;
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(){}
};
struct C{
    P p;
    double r;
    C(const P& p, const double& r) : p(p), r(r) {}
    C(){}
};

namespace std{
    bool operator < (const P& a, const P& b){
        return (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
}
P unit(const P &p){
    return p/abs(p);
}
P rotate(const P &p, double rad){
    return p *P(cos(rad), sin(rad));
}

bool intersectSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) <= 0 ) &&
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) <= 0 );
}
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;
}

P projection(const L& l, const P& p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}
double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}

P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1]-l[0], m[1]-m[0]);
  double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B/A *(m[1]-m[0]);
}
VP crosspointCL(const C &c, const L &l){
    VP ret;
    P mid = projection(l, c.p);
    double d = distanceLP(l, c.p);
    if(EQ(d, c.r)){
        ret.push_back(mid);
    }else if(d < c.r){
        double len = sqrt(c.r*c.r -d*d);
        ret.push_back(mid +len*unit(l[1]-l[0]));
        ret.push_back(mid -len*unit(l[1]-l[0]));
    }
    return ret;
}
VP crosspointCS(const C &c, const L &s){
    VP ret;
    VP cp = crosspointCL(c,s);
    for(int i=0; i<(int)cp.size(); i++){
        if(intersectSP(s, cp[i])){
            ret.push_back(cp[i]);
        }
    }
    return ret;
}

bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}

vector<L> getTangentLine(const C &c, const P &p){
    vector<L> ret;
    P dir = p -c.p;
    if(c.r < abs(dir) +EPS){
        P a = c.p + c.r*unit(dir);
        VP cp = crosspointCL(C(c.p, abs(dir)), L(a, a+dir*P(0,1)));
        for(int i=0; i<(int)cp.size(); i++){
            ret.push_back(L(p, c.p +c.r*unit(cp[i]-c.p)));
        }
    }
    return ret;
}

vector<L> getCommonTangentLine(C a, C b){
    vector<L> ret;
    if(a.p==b.p && EQ(a.r, b.r)) return ret;
    if(a.r < b.r) swap(a,b);
    P ab = b.p -a.p;
    double d = abs(ab);
    if(d+EPS > a.r+b.r){
        ret = getTangentLine(a, a.p +a.r/(a.r+b.r)*ab);
    }
    if(d+EPS > a.r-b.r){
        if(EQ(a.r, b.r)){
            P normal = unit(ab)*P(0,1)*a.r;
            ret.push_back(L(a.p +normal, b.p +normal));
            ret.push_back(L(a.p -normal, b.p -normal));
        }else{
            vector<L> tmp = getTangentLine(a, a.p +a.r/(a.r-b.r)*ab);
            copy(tmp.begin(), tmp.end(), back_inserter(ret));
        }
    }
    return ret;
}

double getAngle(P a, P b, P c){
    b -= a;
    c -= a;
    return abs(arg(b/c));
}

void generate_object(int n, double r, double rr, vector<L> &l, vector<C> &c){
    double theta = PI/(2*n);
    double dr = r / sin(theta);
    l.resize(4);
    c.push_back(C(P(0, 0), dr));
    l[0] = L(rotate(P(rr, 0), theta), rotate(P(-rr, 0), theta));
    l[1] = L(conj(l[0][0]), conj(l[0][1]));
    l[2] = L(P(r, INF), P(r, -INF));
    l[3] = L(-l[2][0], -l[2][1]);
    for(int i=0; i<2; i++){
        for(int j=0; j<2; j++){
            c.push_back(C(l[i][j], r));
        }
    }
    c.push_back(C(P(0, 0), rr +r));
    c.push_back(C(P(0, 0), rr -r));
}

bool in_object(P p, vector<L> &l, vector<C> &c){
    for(int i=0; i<5; i++){
        if(abs(p -c[i].p) +EPS < c[i].r){
            return true;
        }
    }
    if((abs(p.X) +EPS < c[1].r) && (abs(p -c[5].p) +EPS > c[5].r)){
        return true;
    }
    if(abs(p) +EPS < c[5].r && abs(p) > c[6].r +EPS &&
       ccw(l[0][0], l[0][1], p)*ccw(l[1][0], l[1][1], p) == 1){
        return true;
    }
    return false;
}

bool isVisible(L ray, vector<L> &l, vector<C> &c){
    VP cp;
    cp.push_back(ray[0]);
    cp.push_back(ray[1]);
    for(int i=2; i<4; i++){
        if(!isParallel(ray, l[i]) && intersectSS(ray, l[i])){
            cp.push_back(crosspointLL(ray, l[i]));
        }
    }
    for(int i=0; i<7; i++){
        VP tmp = crosspointCS(c[i], ray);
        for(int j=0; j<(int)tmp.size(); j++){
            cp.push_back(tmp[j]);
        }
    }
    sort(cp.begin(), cp.end());
    cp.erase(unique(cp.begin(), cp.end()), cp.end());
    for(int i=0; i<(int)cp.size()-1; i++){
        if(in_object((cp[i+1] +cp[i])/2.0, l, c)){
            return false;
        }
    }
    return true;
}

VP listup(vector<L> &l, vector<C> &c, VP &sg){
    VP ret;
    for(int i=0; i<5; i++){
        for(int j=i+1; j<5; j++){
            vector<L> cl = getCommonTangentLine(c[i], c[j]);
            for(int k=0; k<(int)cl.size(); k++){
                L ray(projection(cl[k], c[i].p), projection(cl[k], c[j].p));
                if(!isVisible(ray, l, c)) continue;
                ret.push_back(ray[0]);
                ret.push_back(ray[1]);
            }
        }
    }
    for(int i=0; i<2; i++){
        for(int j=0; j<6; j++){
            vector<L> tl = getTangentLine(c[j], sg[i]);
            for(int k=0; k<(int)tl.size(); k++){
                L ray(sg[i], projection(tl[k], c[j].p));
                if(!isVisible(ray, l, c)) continue;
                ret.push_back(ray[1]);
            }
        }
    }
    for(int i=0; i<2; i++){
        VP cp = crosspointCL(c[5], l[i]);
        ret.push_back(cp[0]);
        ret.push_back(cp[1]);
    }
    sort(ret.begin(), ret.end());
    ret.erase(unique(ret.begin(), ret.end()), ret.end());
    ret.insert(ret.begin(), sg.begin(), sg.end());
    return ret;
}

vector<vector<double> > make_graph(vector<L> &l, vector<C> &c, VP plist){
    int n = plist.size();
    vector<vector<double> > adj(n, vector<double>(n, INF));
    for(int i=0; i<n; i++){
        if(in_object(plist[i], l, c)) continue;
        for(int j=i+1; j<n; j++){
            if(in_object(plist[j], l, c)) continue;
            if(isVisible(L(plist[i], plist[j]), l, c)){
                adj[i][j] = adj[j][i] = min(adj[j][i], abs(plist[j] -plist[i]));
            }
            for(int k=0; k<6; k++){
                if(EQ(abs(plist[i]-c[k].p), c[k].r) && EQ(abs(plist[j]-c[k].p), c[k].r)){
                    if(k!=5 || plist[i].X *plist[j].X > 0){
                        double theta = getAngle(c[k].p, plist[i], plist[j]);
                        adj[i][j] = adj[j][i] = min(adj[i][j], theta *c[k].r);
                    }
                }
            }
        }
    }    
    return adj;
}

void warshall(vector<vector<double> > &adj){
    int n = adj.size();
    for(int k=0; k<n; k++){
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                adj[i][j] = min(adj[i][j], adj[i][k] +adj[k][j]);
            }
        }
    }
}

int main(){
    cout << fixed;
    cout << setprecision(10);
    while(1){
        int n;
        cin >> n;
        if(n==0) break;
        
        double r,rr;
        cin >> r >> rr;
        VP sg(2);
        for(int i=0; i<2; i++){
            double x,y;
            cin >> x >> y;
            sg[i] = P(x, y);
        }
        if(r/sin(PI/(2*n)) > rr-r +EPS){
            cout << -1 << endl;
            continue;
        }

        vector<L> line;
        vector<C> circle;
        generate_object(n, r, rr, line, circle);        
        VP plist = listup(line, circle, sg);
        vector<vector<double> > adj = make_graph(line, circle, plist);
        warshall(adj);
        cout << adj[0][1] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3552
final_rank: 1

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

const double EPS = 1e-8;
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(){}
};
struct C{
    P p;
    double r;
    C(const P& p, const double& r) : p(p), r(r) {}
    C(){}
};

namespace std{
    bool operator < (const P& a, const P& b){
        return (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
}
P unit(const P &p){
    return p/abs(p);
}
P rotate(const P &p, double rad){
    return p *P(cos(rad), sin(rad));
}

bool intersectSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) <= 0 ) &&
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) <= 0 );
}
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;
}

P projection(const L& l, const P& p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}
double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}

P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1]-l[0], m[1]-m[0]);
  double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B/A *(m[1]-m[0]);
}
VP crosspointCL(const C &c, const L &l){
    VP ret;
    P mid = projection(l, c.p);
    double d = distanceLP(l, c.p);
    if(EQ(d, c.r)){
        ret.push_back(mid);
    }else if(d < c.r){
        double len = sqrt(c.r*c.r -d*d);
        ret.push_back(mid +len*unit(l[1]-l[0]));
        ret.push_back(mid -len*unit(l[1]-l[0]));
    }
    return ret;
}
VP crosspointCS(const C &c, const L &s){
    VP ret;
    VP cp = crosspointCL(c,s);
    for(int i=0; i<(int)cp.size(); i++){
        if(intersectSP(s, cp[i])){
            ret.push_back(cp[i]);
        }
    }
    return ret;
}

bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}

vector<L> getTangentLine(const C &c, const P &p){
    vector<L> ret;
    P dir = p -c.p;
    if(c.r < abs(dir) +EPS){
        P a = c.p + c.r*unit(dir);
        VP cp = crosspointCL(C(c.p, abs(dir)), L(a, a+dir*P(0,1)));
        for(int i=0; i<(int)cp.size(); i++){
            ret.push_back(L(p, c.p +c.r*unit(cp[i]-c.p)));
        }
    }
    return ret;
}

vector<L> getCommonTangentLine(C a, C b){
    vector<L> ret;
    if(a.p==b.p && EQ(a.r, b.r)) return ret;
    if(a.r < b.r) swap(a,b);
    P ab = b.p -a.p;
    double d = abs(ab);
    if(d+EPS > a.r+b.r){
        ret = getTangentLine(a, a.p +a.r/(a.r+b.r)*ab);
    }
    if(d+EPS > a.r-b.r){
        if(EQ(a.r, b.r)){
            P normal = unit(ab)*P(0,1)*a.r;
            ret.push_back(L(a.p +normal, b.p +normal));
            ret.push_back(L(a.p -normal, b.p -normal));
        }else{
            vector<L> tmp = getTangentLine(a, a.p +a.r/(a.r-b.r)*ab);
            copy(tmp.begin(), tmp.end(), back_inserter(ret));
        }
    }
    return ret;
}

double getAngle(P a, P b, P c){
    b -= a;
    c -= a;
    return abs(arg(b/c));
}

//問題なし
void generate_object(int n, double r, double rr, vector<L> &l, vector<C> &c){
    double theta = PI/(2*n);
    double dr = r / sin(theta);
    l.resize(4);
    //中心の円 [0]
    c.push_back(C(P(0, 0), dr));
    //切れ目の境界
    l[0] = L(rotate(P(rr, 0), theta), rotate(P(-rr, 0), theta));
    l[1] = L(conj(l[0][0]), conj(l[0][1]));
    //左右境界の縦線
    l[2] = L(P(r, INF), P(r, -INF));
    l[3] = L(-l[2][0], -l[2][1]);
    //切れ目の4円
    for(int i=0; i<2; i++){
        for(int j=0; j<2; j++){
            c.push_back(C(l[i][j], r));
        }
    }
    //外側 [5]
    c.push_back(C(P(0, 0), rr +r));
    //内側 [6]
    c.push_back(C(P(0, 0), rr -r));
}

//おそらく問題なし
bool in_object(P p, vector<L> &l, vector<C> &c){
    //中心及び４円の中にある
    for(int i=0; i<5; i++){
        if(abs(p -c[i].p) +EPS < c[i].r){
            return true;
        }
    }
    //円の外側かつ棒の中（左右の境界に触れる）
    if((abs(p.X) +EPS < c[1].r) && (abs(p -c[5].p) +EPS > c[5].r)){
        return true;
    }
    //外側の円の中かつ内側の円の外かつ上側もしくは下側
    if(abs(p) +EPS < c[5].r && abs(p) > c[6].r +EPS &&
       ccw(l[0][0], l[0][1], p)*ccw(l[1][0], l[1][1], p) == 1){
        return true;
    }
    return false;
}

bool isVisible(L ray, vector<L> &l, vector<C> &c){
    VP cp;
    cp.push_back(ray[0]);
    cp.push_back(ray[1]);
    //ray(線分)と線、円の交点を列挙
    for(int i=2; i<4; i++){
        if(!isParallel(ray, l[i]) && intersectSS(ray, l[i])){
            cp.push_back(crosspointLL(ray, l[i]));
        }
    }
    for(int i=0; i<7; i++){
        VP tmp = crosspointCS(c[i], ray);
        for(int j=0; j<(int)tmp.size(); j++){
            cp.push_back(tmp[j]);
        }
    }
    //ソートして重複を削除
    sort(cp.begin(), cp.end());
    cp.erase(unique(cp.begin(), cp.end()), cp.end());
    //いずれかの中点がオブジェクトの内部にあればfalseを返す
    for(int i=0; i<(int)cp.size()-1; i++){
        if(in_object((cp[i+1] +cp[i])/2.0, l, c)){
            return false;
        }
    }
    return true;
}

VP listup(vector<L> &l, vector<C> &c, VP &sg){
    VP ret;
    //中５円の共通接線
    for(int i=0; i<5; i++){
        for(int j=i+1; j<5; j++){
            vector<L> cl = getCommonTangentLine(c[i], c[j]);
            for(int k=0; k<(int)cl.size(); k++){
                //接点を追加(通行可能のみ)
                L ray(projection(cl[k], c[i].p), projection(cl[k], c[j].p));
                if(!isVisible(ray, l, c)) continue;
                ret.push_back(ray[0]);
                ret.push_back(ray[1]);
            }
        }
    }
    //スタート、ゴールから引いた接線（外側含む）
    for(int i=0; i<2; i++){
        for(int j=0; j<6; j++){
            vector<L> tl = getTangentLine(c[j], sg[i]);
            for(int k=0; k<(int)tl.size(); k++){
                //接点を追加(通行可能のみ)
                L ray(sg[i], projection(tl[k], c[j].p));
                if(!isVisible(ray, l, c)) continue;
                ret.push_back(ray[1]);
            }
        }
    }
    //上記では障害物内にある点は列挙されない
    //外側の円と4円の境目
    for(int i=0; i<2; i++){
        VP cp = crosspointCL(c[5], l[i]);
        ret.push_back(cp[0]);
        ret.push_back(cp[1]);
    }
    //重複削除
    sort(ret.begin(), ret.end());
    ret.erase(unique(ret.begin(), ret.end()), ret.end());
    ret.insert(ret.begin(), sg.begin(), sg.end());
    return ret;
}

vector<vector<double> > make_graph(vector<L> &l, vector<C> &c, VP plist){
    int n = plist.size();
    vector<vector<double> > adj(n, vector<double>(n, INF));
    //全ての点の組み合わせについて
    for(int i=0; i<n; i++){
        if(in_object(plist[i], l, c)) continue;
        for(int j=i+1; j<n; j++){
            if(in_object(plist[j], l, c)) continue;
            //直線的に行けるなら結ぶ
            if(isVisible(L(plist[i], plist[j]), l, c)){
                adj[i][j] = adj[j][i] = min(adj[j][i], abs(plist[j] -plist[i]));
            }
            //同じ円上に乗っていてるなら
            for(int k=0; k<6; k++){
                if(EQ(abs(plist[i]-c[k].p), c[k].r) && EQ(abs(plist[j]-c[k].p), c[k].r)){
                    //外側の円については左右の境界をまたがないなら
                    if(k!=5 || plist[i].X *plist[j].X > 0){
                        //円上を移動する(短い方)
                        double theta = getAngle(c[k].p, plist[i], plist[j]);
                        adj[i][j] = adj[j][i] = min(adj[i][j], theta *c[k].r);
                    }
                }
            }
        }
    }    
    return adj;
}

void warshall(vector<vector<double> > &adj){
    int n = adj.size();
    for(int k=0; k<n; k++){
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                adj[i][j] = min(adj[i][j], adj[i][k] +adj[k][j]);
            }
        }
    }
}

int main(){
    cout << fixed;
    cout << setprecision(10);
    while(1){
        int n;
        cin >> n;
        if(n==0) break;
        
        double r,rr;
        cin >> r >> rr;
        VP sg(2);
        for(int i=0; i<2; i++){
            double x,y;
            cin >> x >> y;
            sg[i] = P(x, y);
        }
        if(r/sin(PI/(2*n)) > rr-r +EPS){
            cout << -1 << endl;
            continue;
        }

        vector<L> line;
        vector<C> circle;
        generate_object(n, r, rr, line, circle);
        
        VP plist = listup(line, circle, sg);
        vector<vector<double> > adj = make_graph(line, circle, plist);
        warshall(adj);

        /*
        cerr << plist.size() << endl;
        for(int i=0; i<(int)plist.size(); i++){
            cout << plist[i] << endl;
        }
        */
        
        
        cout << adj[0][1] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3744
final_rank: 5

code_snippet: #include<bits/stdc++.h>
#define MAX 5000
#define inf 1<<29
#define linf 1e16
#define eps (1e-6)
#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;
 
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;
 
class Circle{
public:
  Point c;
  double r;
  Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};
 
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);}
double arg(Vector p){ 
  double res=atan2(p.y,p.x);
  if(res<0.0)res+=2*pi;
  return res;
}
 
Point project(Segment s,Point p){
  Vector base=(s.p2-s.p1);
  double r=(dot(p-s.p1,base)/base.norm());
  return (s.p1+base*r);
}
 
double getDistanceLP(Line l,Point p){
  return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}
 
double getDistanceSP(Segment s,Point p){
  if(dot(s.p2-s.p1,p-s.p1)<0.0)return abs(p-s.p1);
  if(dot(s.p1-s.p2,p-s.p2)<0.0)return abs(p-s.p2);
  return getDistanceLP(s,p);
}
 
bool intersect(Circle c,Segment s){
  if(getDistanceSP(s,c.c)-c.r<-eps)return true;
  return false;
}
 
bool intersect(Line L,Segment s){
  return cross(L.p2-L.p1,s.p1-L.p1)*cross(L.p2-L.p1,s.p2-L.p1)<eps;
}
 
bool on(Circle c,Point p){ return equals(abs(c.c-p),c.r); }
 
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;
}
 
pair<Point,Point> getCrossPoints(Circle c,Line l){
  Vector pr=project(l,c.c);
  Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
  double base=sqrt(c.r*c.r-norm(pr-c.c));
  return mp(pr+e*base,pr-e*base);
}
 
Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}
 
Point rotate(Point base,Point a,double r){
  Point b=a-base;
  a.x=b.x*cos((r/180)*M_PI)-b.y*sin((r/180)*M_PI);
  a.y=b.x*sin((r/180)*M_PI)+b.y*cos((r/180)*M_PI);
  a=a+base;
  return a;
}
 
pair<Point,Point> getTangent(Circle c,Point p){
  Vector v=p-c.c;
  double r=acos(c.r/abs(v))*360/(2*pi);
  v=v*c.r/abs(v);
  Point p1=rotate(c.c,c.c+v,r);
  Point p2=rotate(c.c,c.c+v,360-r);
  return mp(p1,p2);
}
 
int intersect(Circle a,Circle b){
  double dis=abs(a.c-b.c),sumr=a.r+b.r,minr=min(a.r,b.r),maxr=max(a.r,b.r);
  if((sumr-dis)<-eps)return 4;
  if(equals(sumr,dis))return 3;
  if((maxr-(dis+minr))<-eps)return 2;
  if(equals(dis+minr,maxr))return 1;
  return 0;
}
 
vector<Line> getCommonTangent(Circle a,Circle b){
  vector<Line> vp;
  int intersection=intersect(a,b);
  if(intersection==0)return vp;
  if(intersection==1){
    Vector v=b.c-a.c;
    if(b.r<a.r)v=(v*a.r)/abs(v);
    else v=(v*a.r*(-1))/abs(v);
    vp.push_back(Line(a.c+v,a.c+v));
    return vp;
  }
  if(intersection==3){
    Vector v=b.c-a.c;
    v=v*a.r/abs(v);
    vp.push_back(Line(a.c+v,a.c+v));
  }
  double d=abs(b.c-a.c),c,s;
  Vector v=(b.c-a.c)/d,v1=v*a.r,v2=v*b.r;
  Point p1,p2;
 
  c=sqrt(d*d-(a.r-b.r)*(a.r-b.r));
  s=(180*asin(c/d))/pi;
 
  if(a.r<b.r){
    vp.push_back(Line(rotate(a.c,a.c+v1,180-s),rotate(b.c,b.c-v2,360-s)));
    vp.push_back(Line(rotate(a.c,a.c+v1,180+s),rotate(b.c,b.c-v2,s)));
  }
  else {
    vp.push_back(Line(rotate(a.c,a.c+v1,s),rotate(b.c,b.c-v2,180+s)));
    vp.push_back(Line(rotate(a.c,a.c+v1,360-s),rotate(b.c,b.c-v2,180-s)));
  }
  if(intersection==2 || intersection==3)return vp;
   
  c=sqrt(d*d-(a.r+b.r)*(a.r+b.r));
  s=(180*asin(c/d))/pi;
   
  vp.push_back(Line(rotate(a.c,a.c+v1,s),rotate(b.c,b.c-v2,s)));
  vp.push_back(Line(rotate(a.c,a.c+v1,360-s),rotate(b.c,b.c-v2,360-s)));
   
  return vp;
}
 
double getAngle(Vector a,Vector b){
  double tmp=dot(a,b)/(abs(a)*abs(b));
  if(tmp<-1.0)tmp=-1.0;
  if(1.0<tmp)tmp=1.0;
  double r=acos(tmp)*180.0/pi;
  return r;
}
 
int n,r,R;
Point s,g;
vector<Point> vp;
vector<pid> e[MAX];
vector<Circle> vc;
Circle small,big,big2;
Line L(Point(0,0),Point(0,1));
 
void init(){
  vp.clear();
  vc.clear();
  FOR(i,0,MAX)e[i].clear();
}
 
void add_edge(int from,int to,double cost){
  e[from].pb(mp(to,cost));
  e[to].pb(mp(from,cost));
}
 
double dijkstra(){
  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[0]=0;
  pq.push(mp(0,0));
 
  while(pq.size()){
    pdi u=pq.top();
    pq.pop();
 
    if(d[u.s]-u.f<-eps)continue;
    if(u.s==1)return d[u.s];
 
    FOR(i,0,e[u.s].size()){
      int next=e[u.s][i].f;
      double cost=d[u.s]+e[u.s][i].s;
      if(cost-d[next]<-eps){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return -1;
}
 
bool in(double targ){
  if(arg(vc[0].c)-targ<-eps && targ-arg(vc[1].c)<-eps)return false;
  if(arg(vc[2].c)-targ<-eps && targ-arg(vc[3].c)<-eps)return false;
  return true;
}
 
bool check(Segment s){
  if(intersect(L,s)){
    Point m=getCrossPointLL(L,s);
    if(R-r<abs(m))return false;
  }
  if(on(small,s.p1) && on(small,s.p2))return true;
  if(on(big,s.p1) && on(big,s.p2))return true;
  FOR(i,0,vc.size()){
    if(on(vc[i],s.p1) && on(vc[i],s.p2))return true;
    if(intersect(vc[i],s))return false;
    if(on(vc[i],s.p1) && !in(arg(s.p1)))return false;
    if(on(vc[i],s.p2) && !in(arg(s.p2)))return false;
  }
  if(intersect(small,s))return false;
  if(intersect(big,s)){
    pair<Point,Point> pp=getCrossPoints(big,s);
    if(ccw(s.p1,s.p2,pp.f)==0 && !in(arg(pp.f)))return false;
    if(ccw(s.p1,s.p2,pp.s)==0 && !in(arg(pp.s)))return false;
  }
  if(intersect(big2,s)){
    pair<Point,Point> pp=getCrossPoints(big2,s);
    if(ccw(s.p1,s.p2,pp.f)==0 && !in(arg(pp.f)))return false;
    if(ccw(s.p1,s.p2,pp.s)==0 && !in(arg(pp.s)))return false;
  }
  return true;
}
 
double getdis(Segment s){
  FOR(i,0,vc.size()){
    if(on(vc[i],s.p1) && on(vc[i],s.p2)){
      double ang=getAngle(vc[i].c-s.p1,vc[i].c-s.p2);
      return 2*pi*vc[i].r*ang/360.0;
    }
  }
  if(on(small,s.p1) && on(small,s.p2)){
    double ang=getAngle(small.c-s.p1,small.c-s.p2);
    return 2*pi*small.r*ang/360.0;
  }
  if(on(big,s.p1) && on(big,s.p2)){
    if(ccw(L.p2,L.p1,s.p1)*ccw(L.p2,L.p1,s.p2)<=0)return inf;
    double ang=getAngle(big.c-s.p1,big.c-s.p2);
    return 2*pi*big.r*ang/360.0;
  }
   
  return abs(s.p1-s.p2);
}
 
bool comp(Circle a,Circle b){
  return arg(a.c)<arg(b.c);
}
 
double solve(){
  double r1 = r/sin(pi/(2*n));
  if(R<r1+r)return -1;
  double y=R*sin(pi/(2*n)),x=sqrt(R*R-y*y);
  small=Circle(Point(0,0),r1);
  big=Circle(Point(0,0),r+R);
  big2=Circle(Point(0,0),R-r);
 
  vc.pb(Circle(Point(x,y),r));
  vc.pb(Circle(Point(-x,y),r));
  vc.pb(Circle(Point(x,-y),r));
  vc.pb(Circle(Point(-x,-y),r));
  sort(all(vc),comp);
  vc.pb(small);
  vc.pb(big);
  vp.pb(s);
  vp.pb(g);
 
  FOR(i,0,vc.size()){
    FOR(j,i+1,vc.size()){
      vector<Line> vl=getCommonTangent(vc[i],vc[j]);
      FOR(k,0,vl.size()){
        vp.pb(vl[k].p1);
        vp.pb(vl[k].p2);
      }
    }
  }
 
  FOR(i,0,vc.size()){
    pair<Point,Point> pp = getTangent(vc[i],s);
    vp.pb(pp.f);vp.pb(pp.s);
    pp = getTangent(vc[i],g);
    vp.pb(pp.f);vp.pb(pp.s);
  }
 
  vc.pop_back();vc.pop_back();
 
  FOR(i,0,vp.size()){
    FOR(j,i+1,vp.size()){
      Segment s(vp[i],vp[j]);
      if(check(s))add_edge(i,j,getdis(s));
    }
  }
  return dijkstra();
}
 
int main()
{
  while(cin>>n && n){
    init();
    cin>>r>>R;
    cin>>s.x>>s.y>>g.x>>g.y;
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3932
final_rank: 4

code_snippet: #include<bits/stdc++.h>
#define MAX 5000
#define inf 1<<29
#define linf 1e16
#define eps (1e-6)
#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;

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;

class Circle{
public:
  Point c;
  double r;
  Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

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);}
double arg(Vector p){ 
  double res=atan2(p.y,p.x);
  if(res<0.0)res+=2*pi;
  return res;
}

Point project(Segment s,Point p){
  Vector base=(s.p2-s.p1);
  double r=(dot(p-s.p1,base)/base.norm());
  return (s.p1+base*r);
}

double getDistanceLP(Line l,Point p){
  return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}

double getDistanceSP(Segment s,Point p){
  if(dot(s.p2-s.p1,p-s.p1)<0.0)return abs(p-s.p1);
  if(dot(s.p1-s.p2,p-s.p2)<0.0)return abs(p-s.p2);
  return getDistanceLP(s,p);
}

bool intersect(Circle c,Segment s){
  if(getDistanceSP(s,c.c)-c.r<-eps)return true;
  return false;
}

bool intersect(Line L,Segment s){
  return cross(L.p2-L.p1,s.p1-L.p1)*cross(L.p2-L.p1,s.p2-L.p1)<eps;
}

bool on(Circle c,Point p){ return equals(abs(c.c-p),c.r); }

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;
}

pair<Point,Point> getCrossPoints(Circle c,Line l){
  Vector pr=project(l,c.c);
  Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
  double base=sqrt(c.r*c.r-norm(pr-c.c));
  return mp(pr+e*base,pr-e*base);
}

Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

Point rotate(Point base,Point a,double r){
  Point b=a-base;
  a.x=b.x*cos((r/180)*M_PI)-b.y*sin((r/180)*M_PI);
  a.y=b.x*sin((r/180)*M_PI)+b.y*cos((r/180)*M_PI);
  a=a+base;
  return a;
}

pair<Point,Point> getTangent(Circle c,Point p){
  Vector v=p-c.c;
  double r=acos(c.r/abs(v))*360/(2*pi);
  v=v*c.r/abs(v);
  Point p1=rotate(c.c,c.c+v,r);
  Point p2=rotate(c.c,c.c+v,360-r);
  return mp(p1,p2);
}

int intersect(Circle a,Circle b){
  double dis=abs(a.c-b.c),sumr=a.r+b.r,minr=min(a.r,b.r),maxr=max(a.r,b.r);
  if((sumr-dis)<-eps)return 4;
  if(equals(sumr,dis))return 3;
  if((maxr-(dis+minr))<-eps)return 2;
  if(equals(dis+minr,maxr))return 1;
  return 0;
}

vector<Line> getCommonTangent(Circle a,Circle b){
  vector<Line> vp;
  int intersection=intersect(a,b);
  if(intersection==0)return vp;
  if(intersection==1){
    Vector v=b.c-a.c;
    if(b.r<a.r)v=(v*a.r)/abs(v);
    else v=(v*a.r*(-1))/abs(v);
    vp.push_back(Line(a.c+v,a.c+v));
    return vp;
  }
  if(intersection==3){
    Vector v=b.c-a.c;
    v=v*a.r/abs(v);
    vp.push_back(Line(a.c+v,a.c+v));
  }
  double d=abs(b.c-a.c),c,s;
  Vector v=(b.c-a.c)/d,v1=v*a.r,v2=v*b.r;
  Point p1,p2;

  c=sqrt(d*d-(a.r-b.r)*(a.r-b.r));
  s=(180*asin(c/d))/pi;

  if(a.r<b.r){
    vp.push_back(Line(rotate(a.c,a.c+v1,180-s),rotate(b.c,b.c-v2,360-s)));
    vp.push_back(Line(rotate(a.c,a.c+v1,180+s),rotate(b.c,b.c-v2,s)));
  }
  else {
    vp.push_back(Line(rotate(a.c,a.c+v1,s),rotate(b.c,b.c-v2,180+s)));
    vp.push_back(Line(rotate(a.c,a.c+v1,360-s),rotate(b.c,b.c-v2,180-s)));
  }
  if(intersection==2 || intersection==3)return vp;
  
  c=sqrt(d*d-(a.r+b.r)*(a.r+b.r));
  s=(180*asin(c/d))/pi;
  
  vp.push_back(Line(rotate(a.c,a.c+v1,s),rotate(b.c,b.c-v2,s)));
  vp.push_back(Line(rotate(a.c,a.c+v1,360-s),rotate(b.c,b.c-v2,360-s)));
  
  return vp;
}

double getAngle(Vector a,Vector b){
  double tmp=dot(a,b)/(abs(a)*abs(b));
  if(tmp<-1.0)tmp=-1.0;
  if(1.0<tmp)tmp=1.0;
  double r=acos(tmp)*180.0/pi;
  return r;
}

int n,r,R;
Point s,g;
vector<Point> vp;
vector<pid> e[MAX];
vector<Circle> vc;
Circle small,big,big2;
Line L(Point(0,0),Point(0,1));

void init(){
  vp.clear();
  vc.clear();
  FOR(i,0,MAX)e[i].clear();
}

void add_edge(int from,int to,double cost){
  e[from].pb(mp(to,cost));
  e[to].pb(mp(from,cost));
}

double dijkstra(){
  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[0]=0;
  pq.push(mp(0,0));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();

    if(d[u.s]-u.f<-eps)continue;
    if(u.s==1)return d[u.s];

    FOR(i,0,e[u.s].size()){
      int next=e[u.s][i].f;
      double cost=d[u.s]+e[u.s][i].s;
      if(cost-d[next]<-eps){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return -1;
}

bool in(double targ){
  if(arg(vc[0].c)-targ<-eps && targ-arg(vc[1].c)<-eps)return false;
  if(arg(vc[2].c)-targ<-eps && targ-arg(vc[3].c)<-eps)return false;
  return true;
}

bool check(Segment s){
  if(intersect(L,s)){
    Point m=getCrossPointLL(L,s);
    if(R-r<abs(m))return false;
  }
  if(on(small,s.p1) && on(small,s.p2))return true;
  if(on(big,s.p1) && on(big,s.p2))return true;
  FOR(i,0,vc.size()){
    if(on(vc[i],s.p1) && on(vc[i],s.p2))return true;
    if(intersect(vc[i],s))return false;
    if(on(vc[i],s.p1) && !in(arg(s.p1)))return false;
    if(on(vc[i],s.p2) && !in(arg(s.p2)))return false;
  }
  if(intersect(small,s))return false;
  if(intersect(big,s)){
    pair<Point,Point> pp=getCrossPoints(big,s);
    if(ccw(s.p1,s.p2,pp.f)==0 && !in(arg(pp.f)))return false;
    if(ccw(s.p1,s.p2,pp.s)==0 && !in(arg(pp.s)))return false;
  }
  if(intersect(big2,s)){
    pair<Point,Point> pp=getCrossPoints(big2,s);
    if(ccw(s.p1,s.p2,pp.f)==0 && !in(arg(pp.f)))return false;
    if(ccw(s.p1,s.p2,pp.s)==0 && !in(arg(pp.s)))return false;
  }
  return true;
}

double getdis(Segment s){
  FOR(i,0,vc.size()){
    if(on(vc[i],s.p1) && on(vc[i],s.p2)){
      double ang=getAngle(vc[i].c-s.p1,vc[i].c-s.p2);
      return 2*pi*vc[i].r*ang/360.0;
    }
  }
  if(on(small,s.p1) && on(small,s.p2)){
    double ang=getAngle(small.c-s.p1,small.c-s.p2);
    return 2*pi*small.r*ang/360.0;
  }
  if(on(big,s.p1) && on(big,s.p2)){
    if(ccw(L.p2,L.p1,s.p1)*ccw(L.p2,L.p1,s.p2)<=0)return inf;
    double ang=getAngle(big.c-s.p1,big.c-s.p2);
    return 2*pi*big.r*ang/360.0;
  }
  
  return abs(s.p1-s.p2);
}

bool comp(Circle a,Circle b){
  return arg(a.c)<arg(b.c);
}

double solve(){
  double r1 = r/sin(pi/(2*n));
  if(R<r1+r)return -1;
  double y=R*sin(pi/(2*n)),x=sqrt(R*R-y*y);
  small=Circle(Point(0,0),r1);
  big=Circle(Point(0,0),r+R);
  big2=Circle(Point(0,0),R-r);

  vc.pb(Circle(Point(x,y),r));
  vc.pb(Circle(Point(-x,y),r));
  vc.pb(Circle(Point(x,-y),r));
  vc.pb(Circle(Point(-x,-y),r));
  sort(all(vc),comp);
  vc.pb(small);
  vc.pb(big);
  vp.pb(s);
  vp.pb(g);

  FOR(i,0,vc.size()){
    FOR(j,i+1,vc.size()){
      vector<Line> vl=getCommonTangent(vc[i],vc[j]);
      FOR(k,0,vl.size()){
        vp.pb(vl[k].p1);
        vp.pb(vl[k].p2);
      }
    }
  }

  FOR(i,0,vc.size()){
    pair<Point,Point> pp = getTangent(vc[i],s);
    vp.pb(pp.f);vp.pb(pp.s);
    pp = getTangent(vc[i],g);
    vp.pb(pp.f);vp.pb(pp.s);
  }

  vc.pop_back();vc.pop_back();

  FOR(i,0,vp.size()){
    FOR(j,i+1,vp.size()){
      Segment s(vp[i],vp[j]);
      if(check(s))add_edge(i,j,getdis(s));
    }
  }
  return dijkstra();
}

int main()
{
  while(cin>>n && n){
    init();
    cin>>r>>R;
    cin>>s.x>>s.y>>g.x>>g.y;
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3908
final_rank: 3

code_snippet: #include<bits/stdc++.h>
#define MAX 5000
#define inf 1<<29
#define linf 1e16
#define eps (1e-6)
#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;

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;

class Circle{
public:
  Point c;
  double r;
  Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

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);}
double arg(Vector p){ 
  double res=atan2(p.y,p.x);
  if(res<0.0)res+=2*pi;
  return res;
}

Point project(Segment s,Point p){
  Vector base=(s.p2-s.p1);
  double r=(dot(p-s.p1,base)/base.norm());
  return (s.p1+base*r);
}

double getDistanceLP(Line l,Point p){
  return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}

double getDistanceSP(Segment s,Point p){
  if(dot(s.p2-s.p1,p-s.p1)<0.0)return abs(p-s.p1);
  if(dot(s.p1-s.p2,p-s.p2)<0.0)return abs(p-s.p2);
  return getDistanceLP(s,p);
}

bool intersect(Circle c,Segment s){
  if(getDistanceSP(s,c.c)-c.r<-eps)return true;
  return false;
}

bool intersect(Line L,Segment s){
  return cross(L.p2-L.p1,s.p1-L.p1)*cross(L.p2-L.p1,s.p2-L.p1)<eps;
}

bool on(Circle c,Point p){ return equals(abs(c.c-p),c.r); }

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;
}

pair<Point,Point> getCrossPoints(Circle c,Line l){
  Vector pr=project(l,c.c);
  Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
  double base=sqrt(c.r*c.r-norm(pr-c.c));
  return mp(pr+e*base,pr-e*base);
}

Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

Point rotate(Point base,Point a,double r){
  Point b=a-base;
  a.x=b.x*cos((r/180)*M_PI)-b.y*sin((r/180)*M_PI);
  a.y=b.x*sin((r/180)*M_PI)+b.y*cos((r/180)*M_PI);
  a=a+base;
  return a;
}

pair<Point,Point> getTangent(Circle c,Point p){
  Vector v=p-c.c;
  double r=acos(c.r/abs(v))*360/(2*pi);
  v=v*c.r/abs(v);
  Point p1=rotate(c.c,c.c+v,r);
  Point p2=rotate(c.c,c.c+v,360-r);
  return mp(p1,p2);
}

int intersect(Circle a,Circle b){
  double dis=abs(a.c-b.c),sumr=a.r+b.r,minr=min(a.r,b.r),maxr=max(a.r,b.r);
  if((sumr-dis)<-eps)return 4;
  if(equals(sumr,dis))return 3;
  if((maxr-(dis+minr))<-eps)return 2;
  if(equals(dis+minr,maxr))return 1;
  return 0;
}

vector<Line> getCommonTangent(Circle a,Circle b){
  vector<Line> vp;
  int intersection=intersect(a,b);
  if(intersection==0)return vp;
  if(intersection==1){
    Vector v=b.c-a.c;
    if(b.r<a.r)v=(v*a.r)/abs(v);
    else v=(v*a.r*(-1))/abs(v);
    vp.push_back(Line(a.c+v,a.c+v));
    return vp;
  }
  if(intersection==3){
    Vector v=b.c-a.c;
    v=v*a.r/abs(v);
    vp.push_back(Line(a.c+v,a.c+v));
  }
  double d=abs(b.c-a.c),c,s;
  Vector v=(b.c-a.c)/d,v1=v*a.r,v2=v*b.r;
  Point p1,p2;

  c=sqrt(d*d-(a.r-b.r)*(a.r-b.r));
  s=(180*asin(c/d))/pi;

  if(a.r<b.r){
    vp.push_back(Line(rotate(a.c,a.c+v1,180-s),rotate(b.c,b.c-v2,360-s)));
    vp.push_back(Line(rotate(a.c,a.c+v1,180+s),rotate(b.c,b.c-v2,s)));
  }
  else {
    vp.push_back(Line(rotate(a.c,a.c+v1,s),rotate(b.c,b.c-v2,180+s)));
    vp.push_back(Line(rotate(a.c,a.c+v1,360-s),rotate(b.c,b.c-v2,180-s)));
  }
  if(intersection==2 || intersection==3)return vp;
  
  c=sqrt(d*d-(a.r+b.r)*(a.r+b.r));
  s=(180*asin(c/d))/pi;
  
  vp.push_back(Line(rotate(a.c,a.c+v1,s),rotate(b.c,b.c-v2,s)));
  vp.push_back(Line(rotate(a.c,a.c+v1,360-s),rotate(b.c,b.c-v2,360-s)));
  
  return vp;
}

double getAngle(Vector a,Vector b){
  double tmp=dot(a,b)/(abs(a)*abs(b));
  if(tmp<-1.0)tmp=-1.0;
  if(1.0<tmp)tmp=1.0;
  double r=acos(tmp)*180.0/pi;
  return r;
}

int n,r,R;
Point s,g;
vector<Point> vp;
vector<pid> e[MAX];
vector<Circle> vc;
Circle small,big,big2;
Line L(Point(0,0),Point(0,1));

void init(){
  vp.clear();
  vc.clear();
  FOR(i,0,MAX)e[i].clear();
}

void add_edge(int from,int to,double cost){
  e[from].pb(mp(to,cost));
  e[to].pb(mp(from,cost));
}

double dijkstra(){
  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[0]=0;
  pq.push(mp(0,0));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();

    if(d[u.s]-u.f<-eps)continue;
    if(u.s==1)return d[u.s];

    FOR(i,0,e[u.s].size()){
      int next=e[u.s][i].f;
      double cost=d[u.s]+e[u.s][i].s;
      if(cost-d[next]<-eps){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return -1;
}

bool in(double targ){
  if(arg(vc[0].c)-targ<-eps && targ-arg(vc[1].c)<-eps)return false;
  if(arg(vc[2].c)-targ<-eps && targ-arg(vc[3].c)<-eps)return false;
  return true;
}

bool check(Segment s){
  if(intersect(L,s)){
    Point m=getCrossPointLL(L,s);
    if(R-r<abs(m))return false;
  }
  if(on(small,s.p1) && on(small,s.p2))return true;
  if(on(big,s.p1) && on(big,s.p2))return true;
  FOR(i,0,vc.size()){
    if(on(vc[i],s.p1) && on(vc[i],s.p2))return true;
    if(intersect(vc[i],s))return false;
    if(on(vc[i],s.p1)){
      double targ=arg(s.p1);
      if(!in(targ))return false;
    }
    if(on(vc[i],s.p2)){
      double targ=arg(s.p2);
      if(!in(targ))return false;
    }
  }
  if(intersect(small,s))return false;
  if(intersect(big,s)){
    pair<Point,Point> pp=getCrossPoints(big,s);
    if(ccw(s.p1,s.p2,pp.f)==0){
       double targ=arg(pp.f);
      if(!in(targ))return false;
    }
    if(ccw(s.p1,s.p2,pp.s)==0){
       double targ=arg(pp.s);
      if(!in(targ))return false;
    }
  }
  if(intersect(big2,s)){
    pair<Point,Point> pp=getCrossPoints(big2,s);
    if(ccw(s.p1,s.p2,pp.f)==0){
       double targ=arg(pp.f);
      if(!in(targ))return false;
    }
    if(ccw(s.p1,s.p2,pp.s)==0){
       double targ=arg(pp.s);
      if(!in(targ))return false;
    }
  }
  return true;
}

double getdis(Segment s){
  FOR(i,0,vc.size()){
    if(on(vc[i],s.p1) && on(vc[i],s.p2)){
      /*double ang=getAngle(vc[i].c-s.p1,vc[i].c-s.p2);
      Point m=rotate(vc[i].c,s.p1,ang/2.0);
      double targ=arg(m);
      if(in(targ))return 2*pi*vc[i].r*ang/360.0;

      ang=getAngle(vc[i].c-s.p2,vc[i].c-s.p1);
      m=rotate(vc[i].c,s.p2,ang/2.0);
      targ=arg(m);
      if(in(targ))return 2*pi*vc[i].r*ang/360.0;*/
      if(!in(arg(s.p1)))return inf;
      if(!in(arg(s.p2)))return inf;
      double ang=min(getAngle(vc[i].c-s.p1,vc[i].c-s.p2),
                     getAngle(vc[i].c-s.p2,vc[i].c-s.p1));
      return 2*pi*vc[i].r*ang/360.0;
    }
  }
  if(on(small,s.p1) && on(small,s.p2)){
    double ang=min(getAngle(small.c-s.p1,small.c-s.p2),
                   getAngle(small.c-s.p2,small.c-s.p1));
    return 2*pi*small.r*ang/360.0;
  }
  if(on(big,s.p1) && on(big,s.p2)){
    if(ccw(L.p2,L.p1,s.p1)*ccw(L.p2,L.p1,s.p2)<=0)return inf;
    double ang=getAngle(big.c-s.p1,big.c-s.p2);
    return 2*pi*big.r*ang/360.0;
  }
  
  return abs(s.p1-s.p2);
}

bool comp(Circle a,Circle b){
  return arg(a.c)<arg(b.c);
}

double solve(){
  double r1 = r/sin(pi/(2*n));
  if(R<r1+r)return -1;
  double y=R*sin(pi/(2*n)),x=sqrt(R*R-y*y);
  small=Circle(Point(0,0),r1);
  big=Circle(Point(0,0),r+R);
  big2=Circle(Point(0,0),R-r);

  vc.pb(Circle(Point(x,y),r));
  vc.pb(Circle(Point(-x,y),r));
  vc.pb(Circle(Point(x,-y),r));
  vc.pb(Circle(Point(-x,-y),r));
  sort(all(vc),comp);
  vc.pb(small);
  vc.pb(big);
  vp.pb(s);
  vp.pb(g);

  FOR(i,0,vc.size()){
    FOR(j,i+1,vc.size()){
      vector<Line> vl=getCommonTangent(vc[i],vc[j]);
      FOR(k,0,vl.size()){
        vp.pb(vl[k].p1);
        vp.pb(vl[k].p2);
      }
    }
  }

  FOR(i,0,vc.size()){
    pair<Point,Point> pp = getTangent(vc[i],s);
    vp.pb(pp.f);vp.pb(pp.s);
    pp = getTangent(vc[i],g);
    vp.pb(pp.f);vp.pb(pp.s);
  }

  vc.pop_back();vc.pop_back();

  FOR(i,0,vp.size()){
    FOR(j,i+1,vp.size()){
      Segment s(vp[i],vp[j]);
      if(check(s))add_edge(i,j,getdis(s));
    }
  }
  return dijkstra();
}

int main()
{
  while(cin>>n && n){
    init();
    cin>>r>>R;
    cin>>s.x>>s.y>>g.x>>g.y;
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3940
final_rank: 6