Problem:
Problem E:
The Two Men of the Japanese Alps
Two experienced climbers are planning a first-ever attempt: they start at two points of the equal altitudes on a mountain range, move back and forth on a single route keeping their altitudes equal, and finally meet with each other at a point on the route. A wise man told them that if a route has no point lower than the start points (of the equal altitudes) there is at least a way to achieve the attempt. This is the reason why the two climbers dare to start planning this fancy attempt.
The two climbers already obtained altimeters (devices that indicate altitude) and communication devices that are needed for keeping their altitudes equal. They also picked up a candidate route for the attempt: the route consists of consequent line segments without branches; the two starting points are at the two ends of the route; there is no point lower than the two starting points of the equal altitudes. An illustration of the route is given in Figure E.1 (this figure corresponds to the first dataset of the sample input).
Figure E.1: An illustration of a route
The attempt should be possible for the route as the wise man said. The two climbers, however, could not find a pair of move sequences to achieve the attempt, because they cannot keep their altitudes equal without a complex combination of both forward and backward moves. For example, for the route illustrated above: a climber starting at
p
1
(say
A
) moves to
s
, and the other climber (say
B
) moves from
p
6
to
p
5
; then
A
moves back to
t
while
B
moves to
p
4
; finally
A
arrives at
p
3
and at the same time
B
also arrives at
p
3
. Things can be much more complicated and thus they asked you to write a program to find a pair of move sequences for them.
There may exist more than one possible pair of move sequences, and thus you are requested to find the pair of move sequences with the shortest length sum. Here, we measure the length along the route surface, i.e., an uphill path from (0, 0) to (3, 4) has the length of 5.
Input
The input is a sequence of datasets.
The first line of each dataset has an integer indicating the number of points
N
(2 ≤
N
≤ 100) on the route. Each of the following
N
lines has the coordinates (
x
i
,
y
i
) (
i
= 1, 2, ... ,
N
) of the points: the two start points are (
x
1
,
y
1
) and (
x
N
,
y
N
); the line segments of the route connect (
x
i
,
y
i
) and (
x
i
+1
,
y
i
+1
) for
i
= 1, 2, ... ,
N
- 1. Here,
x
i
is the horizontal distance along the route from the start point
x
1
, and
y
i
is the altitude relative to the start point
y
1
. All the coordinates are non-negative integers smaller than 1000, and inequality
x
i
<
x
i
+1
holds for
i
= 1, 2, .. ,
N
- 1, and 0 =
y
1
=
y
N
≤
y
i
for
i
= 2, 3, ... ,
N
- 1.
The end of the input is indicated by a line containing a zero.
Output
For each dataset, output the minimum sum of lengths (along the route) of move sequences until the two climbers meet with each other at a point on the route. Each output 
...(truncated)

Submitted solutions:

code_snippet: #define PII pair<int,int>
#define PDD pair<double,double>
#include <bits/stdc++.h>

using namespace std;

const int N=10240;
const double EPS=1E-7;

vector<PDD> v;
int n,cnt,x[N],y[N],f[N],h[N],nextbase[N],prvbase[N],nxt[102][N],prv[102][N];

queue<PII> q;
bool vis[102][N];
double dp[102][N];

double Dis(int x,int y)
{
	return sqrt(pow(v[x].first-v[y].first,2)+pow(v[x].second-v[y].second,2));
}

int dcmp(double x,double y)
{
	return fabs(x-y)<EPS?0:(x>y?1:-1);
}

bool Inside(int x,int l,int r)
{
	if(l>r) swap(l,r);
	return l<x && x<r;
}

void Move(int x,int y,int drx,int dry,double d)
{
	int nx,ny;
	if(drx)
		nx=nextbase[x];
	else
		nx=prvbase[x];
	if(nx==-1) return;

	if(dry)
		ny=nxt[nx][y];
	else
		ny=prv[nx][y];

	if(ny==-1) return;

	assert(!dcmp(v[f[nx]].second,v[ny].second));

	d+=Dis(x,f[nx])+Dis(y,ny);

	if(dcmp(dp[nx][ny],d)==1)
	{
		dp[nx][ny]=d;
		if(!vis[nx][ny])
			vis[nx][ny]=1,q.push(PII(nx,ny));
	}
}

double SPFA()
{
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++)
		for(int j=0;j<cnt;j++)
			dp[i][j]=1E14;

	dp[1][cnt-1]=0,vis[1][cnt-1]=1;
	for(q.push(PII(1,cnt-1));!q.empty();q.pop())
	{
		PII u=q.front();
		int x=u.first,y=u.second; 
		double d=dp[x][y]; x=f[x];

		if(x==y)
		{
			vis[u.first][y]=0;
			continue;
		}
		assert(!dcmp(v[x].second,v[y].second));

		for(int i=0;i<2;i++)
			for(int j=0;j<2;j++)
				Move(x,y,i,j,d),Move(y,x,i,j,d);
		vis[u.first][y]=0;
	}

	double res=1E14;
	for(int i=1;i<=n;i++)
	{
		int u=f[i];
		res=min(res,dp[i][u]);
	}
	return res;
}

int main()
{
	for(;cin>>n,n;)
	{
		v.clear();
		memset(f,0,sizeof(f));
		memset(h,0,sizeof(h));
		for(int i=1;i<=n;i++)
			scanf("%d%d",x+i,y+i);

		for(int i=1;i<n;i++)
		{
			bool flag=1;
			for(int j=1;j<i;j++)
				if(y[i]==y[j])
				{
					flag=0;
					break;
				}
			if(!flag)
				continue;

			for(int j=1;j<n;j++)
				if(Inside(y[i],y[j],y[j+1]))
					v.push_back(PDD(double(x[j+1]-x[j])/(y[j+1]-y[j])*(y[i]-y[j])+x[j],y[i]));
		}
		for(int i=1;i<=n;i++)
			v.push_back(PDD(x[i],y[i]));
		sort(v.begin(),v.end()),cnt=v.size();

/*
		for(int i=0;i<cnt;i++)
			cout<<v[i].first<<" "<<v[i].second<<endl;
*/

		for(int i=1;i<=n;i++)
			for(int j=0;j<cnt;j++)
				if(!dcmp(v[j].first,x[i]))
				{
					f[i]=j,h[j]=i;
					break;
				}

		for(int i=0,k=-1;i<cnt;i++)
		{
			prvbase[i]=k;
			if(h[i]) k=h[i];
		}

		for(int i=cnt-1,k=-1;i>=0;i--)
		{
			nextbase[i]=k;
			if(h[i]) k=h[i];
		}

		/*for(int i=0;i<cnt;i++)
			cout<<i<<" "<<nextbase[i]<<endl;*/

		for(int i=1;i<=n;i++)
			for(int j=0,k=-1;j<cnt;j++)
			{
				if(!dcmp(v[j].second,y[i]))
					k=j;
				prv[i][j]=k;

				if(dcmp(v[j].second,y[i]) && h[j])
					k=-1;
			}

		for(int i=n;i>=1;i--)
			for(int j=cnt-1,k=-1;j>=0;j--)
			{
				if(!dcmp(v[j].second,y[i]))
					k=j;
				nxt[i][j]=k;

				if(dcmp(v[j].second,y[i]) && h[j])
					k=-1;
			}

		printf("%.9f\n",SPFA());
	}
}
accuracy: 1
time_ms: 50
memory_kb: 19596
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (n); i++)
#define srep(i, s, t) for(int i = (s); i < (t); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
using i64 = long long;
using f64 = double;
i64 floor_div(const i64 n, const i64 d) { assert(d != 0); return n / d - static_cast<i64>((n ^ d) <  0 && n % d != 0); }
i64  ceil_div(const i64 n, const i64 d) { assert(d != 0); return n / d + static_cast<i64>((n ^ d) >= 0 && n % d != 0); }

f64 solve(int n) {
    vector<f64> ax(n), ay(n);
    rep(i, n) cin >> ax[i] >> ay[i];

    vector<f64> vy = ay;
    sort(vy.begin(), vy.end());
    vy.erase(unique(vy.begin(), vy.end()), vy.end());
    const int m = vy.size();

    vector<f64> x, y;
    rep(i, n) {
        x.push_back(ax[i]);
        y.push_back(ay[i]);
        if(i + 1 < n) {
            if(ay[i] < ay[i + 1]) {
                rep(k, m) if(ay[i] < vy[k] and vy[k] < ay[i + 1]) {
                    x.push_back(ax[i] + (ax[i + 1] - ax[i]) * (vy[k] - ay[i]) / (ay[i + 1] - ay[i]));
                    y.push_back(vy[k]);
                }
            } else {
                for(int k = m - 1; k >= 0; k--) if(ay[i + 1] < vy[k] and vy[k] < ay[i]) {
                    x.push_back(ax[i] + (ax[i + 1] - ax[i]) * (vy[k] - ay[i]) / (ay[i + 1] - ay[i]));
                    y.push_back(vy[k]);
                }
            }
        }
    }

    const int sz = x.size();
    const f64 INF = 1e18;
    map<pair<int, int>, f64> dp;
    queue<pair<int, int>> q;
    dp[{0, sz - 1}] = 0;
    q.push({0, sz - 1});
    while(not q.empty()) {
        auto [i, j] = q.front(); q.pop();
        for(int ni : {i - 1, i, i + 1}) {
            for(int nj : {j - 1, j, j + 1}) {
                if(0 <= ni and ni <= nj and nj < sz and y[ni] == y[nj]) {
                    const f64 ci = hypot(x[i] - x[ni], y[i] - y[ni]);
                    const f64 cj = hypot(x[j] - x[nj], y[j] - y[nj]);
                    if(not dp.count({ni, nj})) dp[{ni, nj}] = INF;
                    if(chmin(dp[{ni, nj}], dp[{i, j}] + ci + cj)) q.push({ni, nj});
                }
            }
        }
    }
    f64 ans = INF;
    rep(i, sz) chmin(ans, dp[{i, i}]);
    return ans;
}

int main() {
    cin.tie(0)->sync_with_stdio(0);
    
    while(true) {
        int n; cin >> n; if(n == 0) return 0;
        cout << fixed << setprecision(20) << solve(n) << "\n";
    }
}
accuracy: 1
time_ms: 960
memory_kb: 6340
final_rank: 12

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
while(1) {
    int N;
    cin >> N;
    if (N == 0) return 0;
    vector<int> X(N), Y(N), YS;
    rep(i,0,N) cin >> X[i] >> Y[i], YS.push_back(Y[i]);
    UNIQUE(YS);
    int M = YS.size();
    N--;
    auto in = [&](int A, int H) -> bool {
        if (Y[A] <= Y[A+1]) return Y[A] <= YS[H] && YS[H] <= Y[A+1];
        else return Y[A+1] <= YS[H] && YS[H] <= Y[A];
    };
    auto Dist = [&](int A, double H) -> double {
        if (Y[A] == Y[A+1]) return (double)(X[A+1]-X[A]);
        H = abs(H);
        double DX = (double)(X[A+1]-X[A]), DY = (double)(abs(Y[A+1]-Y[A]));
        return sqrt(DX*DX+DY*DY)*H/DY;
    };
    vector DP(N,vector(N,vector<double>(M,inf)));
    priority_queue<tuple<double,int,int,int>,vector<tuple<double,int,int,int>>,greater<tuple<double,int,int,int>>> PQ;
    DP[0][N-1][0] = 0;
    PQ.push({0,0,N-1,0});
    while(!PQ.empty()) {
        auto [D,A,B,H] = PQ.top();
        PQ.pop();
        if (D > DP[A][B][H]) continue;
        double ND;
        int NA, NB, NH;
        if (A != 0 && Y[A] == YS[H]) {
            ND = D + Dist(A,0.0);
            NA = A-1;
            NB = B;
            NH = H;
            if (chmin(DP[NA][NB][NH],ND)) PQ.push({ND,NA,NB,NH});
        }
        if (A != N-1 && Y[A+1] == YS[H]) {
            ND = D + Dist(A,0.0);
            NA = A+1;
            NB = B;
            NH = H;
            if (chmin(DP[NA][NB][NH],ND)) PQ.push({ND,NA,NB,NH});
        }
        if (B != 0 && Y[B] == YS[H]) {
            ND = D + Dist(B,0.0);
            NA = A;
            NB = B-1;
            NH = H;
            if (chmin(DP[NA][NB][NH],ND)) PQ.push({ND,NA,NB,NH});
        }
        if (B != N-1 && Y[B+1] == YS[H]) {
            ND = D + Dist(B,0.0);
            NA = A;
            NB = B+1;
            NH = H;
            if (chmin(DP[NA][NB][NH],ND)) PQ.push({ND,NA,NB,NH});
        }
        if (H != 0 && in(A,H-1) && in(B,H-1)) {
            ND = D + Dist(A,YS[H]-YS[H-1]) + Dist(B,YS[H]-YS[H-1]);
            NA = A;
            NB = B;
            NH = H-1;
            if (chmin(DP[NA][NB][NH],ND)) PQ.push({ND,NA,NB,NH});
        }
        if (H != M-1 && in(A,H+1) && in(B,H+1)) {
            ND = D + Dist(A,YS[H+1]-YS[H]) + Dist(B,YS[H+1]-YS[H]);
            NA = A;
            NB = B;
            NH = H+1;
            if (chmin(DP[NA][NB][NH],ND)) PQ.push({ND,NA,NB,NH});
        }
    }
    double ANS = inf;
    rep(i,0,N) {
        rep(j,0,M) {
            if (DP[i][i][j] < inf) chmin(ANS,DP[i][i][j]+Dist(i,0.0));
        }
    }
    printf("%.12f\n",ANS);
}
}
accuracy: 1
time_ms: 300
memory_kb: 11360
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i, n) for (int i = 0; i < (n); i++)
#define per(i, n) for (int i = (n)-1; i >= 0; i--)
#define rep2(i, l, r) for (int i = (l); i < (r); i++)
#define per2(i, l, r) for (int i = (r)-1; i >= (l); i--)
#define each(e, x) for (auto &e : x)
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define eb emplace_back
#define MM << ' ' <<
#define TT template <typename T>
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

TT bool chmin(T &x, T y) { return x > y ? (x = y, true) : false; }
TT bool chmax(T &x, T y) { return x < y ? (x = y, true) : false; }

TT using minheap = priority_queue<T, vector<T>, greater<T>>;
TT using maxheap = priority_queue<T>;

TT void print(vector<T> v, T x = 0) {
    int n = sz(v);
    rep(i, n) cout << v[i] + x << (i == n - 1 ? '\n' : ' ');
    if (n == 0) cout << '\n';
}

TT void printn(vector<T> v, T x = 0) {
    int n = sz(v);
    rep(i, n) cout << v[i] + x << '\n';
}

TT void rearrange(vector<T> &v) {
    sort(all(v));
    v.erase(unique(all(v)), end(v));
}

TT int lb(vector<T> &v, T x) { return lower_bound(all(v), x) - begin(v); }
TT int ub(vector<T> &v, T x) { return upper_bound(all(v), x) - begin(v); }

const int inf = (1 << 30) - 1;
const ll INF = (1LL << 60) - 1;

struct io_setup {
    io_setup() {
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cout << fixed << setprecision(15);
    }
} io_setup;

int main() {
    while (1) {
        int n;
        cin >> n;
        if (!n)
            break;
        vector<int> x(n), y(n);
        rep(i, n) cin >> x[i] >> y[i];
        vector<int> ys = y;
        rearrange(ys);
        int m = sz(ys);
        rep(i, n) y[i] = lb(ys, y[i]);
        y.eb(0);
        using Real = double;
        vector dp(n, vector(n, vector(m, (Real)1e9)));
        minheap<pair<Real, pair<int, pii>>> que;
        auto in = [&](int idx, int h) {
            return (min(y[idx], y[idx + 1]) <= h && h <= max(y[idx], y[idx + 1]));
        };
        rep(i, n - 1) rep(j, m) if (in(i, j)) dp[i][i][j] = 0, que.emplace(0, pair(j, pair(i, i)));
        auto dist = [&](int idx, int y1, int y2) {
            double dy = abs(ys[y1] - ys[y2]);
            double dx = (x[idx + 1] - x[idx]) * (dy / abs(ys[y[idx]] - ys[y[idx + 1]]));
            return sqrt(dx * dx + dy * dy);
        };
        while (sz(que)) {
            auto [nd, huv] = que.top();
            auto [nh, uv] = huv;
            auto [u, v] = uv;
            que.pop();
            if (nd > dp[u][v][nh] + 1e-6)
                continue;
            rep(h, m) {
                if (h != nh && in(u, h) && in(v, h)) {
                    Real ned = nd + dist(u, nh, h) + dist(v, nh, h);
                    if (chmin(dp[u][v][h], ned))
                        que.emplace(ned, pair(h, pair(u, v)));
                }
            }
            if (u > 0) {
                int cost = (y[u - 1] == y[u] ? x[u] - x[u - 1] : 0);
                if (nh == y[u] && chmin(dp[u - 1][v][nh], nd + cost))
                    que.emplace(nd + cost, pair(nh, pair(u - 1, v)));
            }
            if (u < n - 1) {
                int cost = (y[u] == y[u + 1] ? x[u + 1] - x[u] : 0);
                if (nh == y[u + 1] && chmin(dp[u + 1][v][nh], nd + cost))
                    que.emplace(nd + cost, pair(nh, pair(u + 1, v)));
            }
            if (v > 0) {
                int cost = (y[v - 1] == y[v] ? x[v] - x[v - 1] : 0);
                if (nh == y[v] && chmin(dp[u][v - 1][nh], nd + cost))
                    que.emplace(nd + cost, pair(nh, pair(u, v - 1)));
            }
            if (v < n - 1) {
                int cost = (y[v] == y[v + 1] ? x[v + 1] - x[v] : 0);
                if (nh == y[v + 1] && chmin(dp[u][v + 1][nh], nd + cost))
                    que.emplace(nd + cost, pair(nh, pair(u, v + 1)));
            }            
        }
        cout << dp[0][n - 1][0] << endl;
    }
}
accuracy: 1
time_ms: 6350
memory_kb: 12048
final_rank: 16

code_snippet: #include <iostream>
#include <cmath>
#include <queue>
#include <tuple>
#include <vector>
#include <algorithm>
using namespace std;

// MLE がきつい…
int N;
int X[10009], Y[10009];
int Height[10009];
int Henkan[10009];
double Dist[109][109][109];
double Len[10009];
vector<pair<double, double>> List;
vector<int> ID[10009];

void Initialize() {
	List.clear();
	for (int i = 0; i < 10009; i++) {
		X[i] = 0; Y[i] = 0; Height[i] = 0; Henkan[i] = 0;
		Len[i] = 0; ID[i].clear();
	}
}

int main() {
	while (true) {
		// Step 1. Input
		Initialize();
		cin >> N; if (N == 0) break;
		for (int i = 1; i <= N; i++) cin >> X[i] >> Y[i];

		// Step 2. Sorting
		vector<int> vec;
		for (int i = 1; i <= N; i++) vec.push_back(Y[i]);
		sort(vec.begin(), vec.end());
		vec.erase(unique(vec.begin(), vec.end()), vec.end());

		// Step 3. Enumerate Checkpoint
		for (int i = 1; i <= N - 1; i++) {
			int pos1 = lower_bound(vec.begin(), vec.end(), Y[i + 0]) - vec.begin();
			int pos2 = lower_bound(vec.begin(), vec.end(), Y[i + 1]) - vec.begin();
			if (pos1 < pos2) {
				for (int j = pos1 + 1; j <= pos2 - 1; j++) {
					double py = vec[j];
					double px = 1.0 * X[i + 0] + 1.0 * (X[i + 1] - X[i + 0]) * (py - Y[i + 0]) / (Y[i + 1] - Y[i + 0]);
					List.push_back(make_pair(px, py));
				}
			}
			if (pos1 > pos2) {
				for (int j = pos1 - 1; j >= pos2 + 1; j--) {
					double py = vec[j];
					double px = 1.0 * X[i + 0] + 1.0 * (X[i + 1] - X[i + 0]) * (Y[i + 0] - py) / (Y[i + 0] - Y[i + 1]);
					List.push_back(make_pair(px, py));
				}
			}
		}
		for (int i = 1; i <= N; i++) List.push_back(make_pair(1.0 * X[i], 1.0 * Y[i]));
		sort(List.begin(), List.end());
		for (int i = 0; i < List.size() - 1; i++) {
			double diff_x = abs(List[i + 1].first - List[i].first);
			double diff_y = abs(List[i + 1].second - List[i].second);
			Len[i] = sqrt(diff_x * diff_x + diff_y * diff_y);
		}

		// Step 4. Enumerate CheckPoint 2
		for (int i = 0; i < List.size(); i++) {
			int pos1 = lower_bound(vec.begin(), vec.end(), List[i].second) - vec.begin();
			Henkan[i] = ID[pos1].size();
			Height[i] = pos1;
			ID[pos1].push_back(i);
		}
		
		// Step 5. Dijkstra
		priority_queue<tuple<double, int, int, int>, vector<tuple<double, int, int, int>>, greater<tuple<double, int, int, int>>> Q;
		for (int i = 0; i <= N; i++) {
			for (int j = 0; j <= N; j++) {
				for (int k = 0; k <= N; k++) Dist[i][j][k] = 1e9;
			}
		}
		Dist[0][Henkan[0]][Henkan[List.size() - 1]] = 0;
		Q.push(make_tuple(0, 0, Henkan[0], Henkan[List.size() - 1]));

		// Step 6. Dijkstra Main
		while (!Q.empty()) {
			int val1 = get<1>(Q.top());
			int val2 = get<2>(Q.top());
			int val3 = get<3>(Q.top());
			int pos1 = ID[val1][val2];
			int pos2 = ID[val1][val3];
			Q.pop();
			for (int j = -1; j <= 1; j++) {
				for (int k = -1; k <= 1; k++) {
					int nex1 = pos1 + j; if (nex1 < 0 || nex1 >= List.size()) continue;
					int nex2 = pos2 + k; if (nex2 < 0 || nex2 >= List.size()) continue;
					if (List[nex1].second != List[nex2].second) continue;
					double cost = 0;
					if (j != 0) cost += Len[min(pos1, nex1)];
					if (k != 0) cost += Len[min(pos2, nex2)];
					int cur1 = Height[nex1];
					int cur2 = Henkan[nex1];
					int cur3 = Henkan[nex2];
					if (Dist[cur1][cur2][cur3] > Dist[val1][val2][val3] + cost) {
						Dist[cur1][cur2][cur3] = Dist[val1][val2][val3] + cost;
						Q.push(make_tuple(Dist[cur1][cur2][cur3], cur1, cur2, cur3));
					}
				}
			}
		}

		// Step 7. Output
		double Answer = 1e9;
		for (int i = 0; i < List.size(); i++) Answer = min(Answer, (double)Dist[Height[i]][Henkan[i]][Henkan[i]]);
		printf("%.12lf\n", Answer);
	}
	return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 13944
final_rank: 7

code_snippet: #include "bits/stdc++.h"
using namespace std;

typedef string::const_iterator State;
#define eps 1e-8L
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL
#define MOD 998244353LL
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef long double ld;
#define REP(a, b) for (long long(a) = 0; (a) < (b); ++(a))
#define ALL(x) (x).begin(), (x).end()

#define int long long

struct info
{
  ld d;
  int l, r;
  info(ld d, int l, int r) : d(d), l(l), r(r) {}
  info() {}
  bool operator<(const info &a) const
  {
    return d > a.d;
  }
};

void solve()
{
  int n;
  cin >> n;
  if (n == 0)
    exit(0);
  vector<pair<ld, ld>> inputs;
  REP(i, n)
  {
    ld a, b;
    cin >> a >> b;
    inputs.push_back({a, b});
  }
  REP(i, n)
  {
    REP(j, n - 1)
    {
      if ((inputs[j].second < inputs[i].second and inputs[i].second < inputs[j + 1].second) || (inputs[j + 1].second < inputs[i].second and inputs[i].second < inputs[j].second))
      {
        double rate = (inputs[i].second - inputs[j].second) / (inputs[j + 1].second - inputs[j].second);
        inputs.push_back(make_pair(inputs[j].first + rate * (inputs[j + 1].first - inputs[j].first), inputs[i].second));
      }
    }
  }
  sort(ALL(inputs));
  inputs.erase(unique(inputs.begin(), inputs.end()), inputs.end());

  int m = inputs.size();
  priority_queue<info> wait;
  wait.push(info(0, 0, m - 1));
  map<pair<int, int>, ld> costs;
  costs[{0, m - 1}] = 0;
  ld ans = 1e18;
  while (!wait.empty())
  {
    ld d = wait.top().d;
    int l = wait.top().l;
    int r = wait.top().r;
    wait.pop();
    if (d > costs[{l, r}] + eps)
      continue;
    if (l == r)
      ans = min(ans, d);
    for (int i = -1; i <= 1; i += 1)
    {
      for (int j = -1; j <= 1; j += 1)
      {
        if (l + i < 0 or m <= l + i)
          continue;
        if (r + j < 0 or m <= r + j)
          continue;
        if (abs(inputs[l + i].second - inputs[r + j].second) < eps)
        {
          ld x1 = inputs[l].first - inputs[l + i].first;
          ld x2 = inputs[r].first - inputs[r + j].first;
          ld y1 = inputs[l].second - inputs[l+i].second;
          ld y2 = inputs[r].second - inputs[r+j].second;
          ld nd = d + sqrt(x1 * x1 + y1 * y1) + sqrt(x2 * x2 + y2 * y2);
          pair<double, double> nlr(l + i, r + j);
          if(costs.count(nlr) == 0 or nd + eps < costs[nlr]){
            costs[nlr] = nd;
            wait.push(info(nd, l + i, r + j));
          }
        }
      }
    }
  }
  cout << ans << endl;
}
#undef int

// generated by oj-template v4.7.2
// (https://github.com/online-judge-tools/template-generator)
int main()
{
  // Fasterize input/output script
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(10);
  // scanf/printf user should delete this fasterize input/output script

  int t = 10000;
  // cin >> t; // comment out if solving multi testcase
  for (int testCase = 1; testCase <= t; ++testCase)
  {
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 1780
memory_kb: 10792
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)

using T = tuple<double, int, int>;

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int) v.size(); ++i) {
        os << v[i];
        if (i < (int) v.size() - 1) os << " ";
    }
    return os;
}

constexpr int INF = 1e9;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    while (1) {
        int N;
        cin >> N;
        if (N == 0) break;
        vector<int> x(N), y(N), ys;
        rep(i,0,N) {
            cin >> x[i] >> y[i];
            ys.push_back(y[i]);
        }
        sort(ys.begin(), ys.end());
        ys.erase(unique(ys.begin(), ys.end()), ys.end());
        vector<double> xx;
        vector<int> yy;
        rep(i,0,N-1) {
            vector<pair<double, int>> t;
            t.push_back({x[i], y[i]});
            for (int v : ys) {
                if (v <= min(y[i], y[i+1]) || max(y[i], y[i+1]) <= v) continue;
                t.push_back({x[i]+1.0*(x[i+1]-x[i])*(v-y[i])/(y[i+1]-y[i]), v});
            }
            sort(t.begin(), t.end());
            for (auto [u, v] : t) xx.push_back(u), yy.push_back(v);
        }
        xx.push_back(x[N-1]);
        yy.push_back(0);
        int n = xx.size();
        set<pair<int, int>> done;

        priority_queue<T, vector<T>, greater<>> pq;
        pq.push({0, 0, n-1});
        while (!pq.empty()) {
            auto [d, i, j] = pq.top(); pq.pop();
            if (i == j) {
                cout << d << "\n";
                break;
            }
            if (done.count({i,j})) continue;
            done.insert({i,j});
            rep(di,-1,2) rep(dj,-1,2) {
                if (di == 0 && dj == 0) continue;
                int ni = i+di, nj = j+dj;
                if (ni > nj || ni < 0 || nj >= n || yy[ni] != yy[nj]) continue;
                double nd = d;
                nd += sqrt(pow(xx[ni]-xx[i], 2)+pow(yy[ni]-yy[i], 2));
                nd += sqrt(pow(xx[nj]-xx[j], 2)+pow(yy[nj]-yy[j], 2));
                pq.push({nd, ni, nj});
            }
        }
    }
}
accuracy: 1
time_ms: 130
memory_kb: 4788
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct node {
    double x, y;
    node(double x, double y) : x(x), y(y) {}
};

double dist(const node& a, const node& b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }

bool solve() {
    int N;
    cin >> N;
    if (N == 0) return false;
    vector<int> x(N), y(N);
    for (int i = 0; i < N; i++) cin >> x[i] >> y[i];

    vector<int> ys = y;
    sort(ys.begin(), ys.end());
    ys.erase(unique(ys.begin(), ys.end()), ys.end());
    vector<node> vs;
    int sz = ys.size();
    for (int i = 0; i < N; i++) {
        vs.emplace_back(x[i], y[i]);
        if (i == N - 1) break;
        double d = double(x[i + 1] - x[i]) / abs(y[i + 1] - y[i]);
        if (y[i] < y[i + 1]) {
            for (int j = 0; j < sz; j++) {
                if (y[i] < ys[j] and ys[j] < y[i + 1]) {
                    vs.emplace_back(x[i] + d * (ys[j] - y[i]), ys[j]);
                }
            }
        } else {
            for (int j = sz - 1; j >= 0; j--) {
                if (ys[j] < y[i] and y[i + 1] < ys[j]) {
                    vs.emplace_back(x[i] + d * (y[i] - ys[j]), ys[j]);
                }
            }
        }
    }

    int n = vs.size();
    vector<map<int, double>> dp(n);
    priority_queue<tuple<double, int, int>> pq;
    dp[0][n - 1] = 0;
    pq.emplace(-dp[0][n - 1], 0, n - 1);

    while (!pq.empty()) {
        auto t = pq.top();
        pq.pop();
        double val;
        int a, b;
        tie(val, a, b) = t;
        val *= -1;
        if (dp[a][b] < val) continue;
        if (a == b) {
            cout << val << '\n';
            return true;
        }
        for (int da : {-1, 0, 1}) {
            for (int db : {-1, 0, 1}) {
                int na = a + da, nb = b + db;
                if (na < 0 or n <= na or nb < 0 or n <= nb) continue;
                if (vs[na].y != vs[nb].y) continue;
                double cost = val + dist(vs[a], vs[na]) + dist(vs[b], vs[nb]);
                if (!dp[na].count(nb) or cost < dp[na][nb]) {
                    dp[na][nb] = cost;
                    pq.emplace(-cost, na, nb);
                }
            }
        }
    }

    return true;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    while (solve())
        ;
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 5528
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct node {
    double x, y;
    node(double x, double y) : x(x), y(y) {}
};

double dist(const node& a, const node& b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }

bool solve() {
    int N;
    cin >> N;
    if (N == 0) return false;
    vector<int> x(N), y(N);
    for (int i = 0; i < N; i++) cin >> x[i] >> y[i];

    vector<int> ys = y;
    sort(ys.begin(), ys.end());
    ys.erase(unique(ys.begin(), ys.end()), ys.end());
    vector<node> vs;
    int sz = ys.size();
    for (int i = 0; i < N; i++) {
        vs.emplace_back(x[i], y[i]);
        if (i == N - 1) break;
        double d = double(x[i + 1] - x[i]) / abs(y[i + 1] - y[i]);
        if (y[i] < y[i + 1]) {
            for (int j = 0; j < sz; j++) {
                if (y[i] < ys[j] and ys[j] < y[i + 1]) {
                    vs.emplace_back(x[i] + d * (ys[j] - y[i]), ys[j]);
                }
            }
        } else {
            for (int j = sz - 1; j >= 0; j--) {
                if (ys[j] < y[i] and y[i + 1] < ys[j]) {
                    vs.emplace_back(x[i] + d * (y[i] - ys[j]), ys[j]);
                }
            }
        }
    }

    int n = vs.size();
    vector<map<int, double>> dp(n);
    priority_queue<tuple<double, int, int>> pq;
    dp[0][n - 1] = 0;
    pq.emplace(-dp[0][n - 1], 0, n - 1);

    while (!pq.empty()) {
        auto t = pq.top();
        pq.pop();
        double val;
        int a, b;
        tie(val, a, b) = t;
        val *= -1;
        if (dp[a][b] < val) continue;
        for (int da : {-1, 0, 1}) {
            for (int db : {-1, 0, 1}) {
                int na = a + da, nb = b + db;
                if (na < 0 or n <= na or nb < 0 or n <= nb) continue;
                if (vs[na].y != vs[nb].y) continue;
                double cost = val + dist(vs[a], vs[na]) + dist(vs[b], vs[nb]);
                if (!dp[na].count(nb) or cost < dp[na][nb]) {
                    dp[na][nb] = cost;
                    pq.emplace(-cost, na, nb);
                }
            }
        }
    }

    double ans = 1e9;
    for (int i = 0; i < n; i++) {
        if (dp[i].count(i)) {
            ans = min(ans, dp[i][i]);
        }
    }

    cout << ans << '\n';
    return true;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    while (solve())
        ;
    return 0;
}
accuracy: 1
time_ms: 590
memory_kb: 9364
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct vertex {
    int l, r;
    double x;
    int y, id;
    vertex(int l, int r, double x, int y, int id) : l(l), r(r), x(x), y(y), id(id) {}
};

double dist(const vertex& a, const vertex& b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }

bool solve() {
    int N;
    cin >> N;
    if (N == 0) return false;
    vector<int> x(N), y(N);
    for (int i = 0; i < N; i++) cin >> x[i] >> y[i];

    vector<int> ys = y;
    sort(ys.begin(), ys.end());
    ys.erase(unique(ys.begin(), ys.end()), ys.end());
    vector<vertex> vs;
    int sz = ys.size(), n = 0;
    for (int i = 0; i < N; i++) {
        vs.emplace_back(i, i, x[i], y[i], n++);
        if (i == N - 1) break;
        double d = double(x[i + 1] - x[i]) / abs(y[i + 1] - y[i]);
        if (y[i] < y[i + 1]) {
            for (int j = 0; j < sz; j++) {
                if (y[i] < ys[j] and ys[j] < y[i + 1]) {
                    vs.emplace_back(i, i + 1, x[i] + d * (ys[j] - y[i]), ys[j], n++);
                }
            }
        } else {
            for (int j = sz - 1; j >= 0; j--) {
                if (ys[j] < y[i] and y[i + 1] < ys[j]) {
                    vs.emplace_back(i, i + 1, x[i] + d * (y[i] - ys[j]), ys[j], n++);
                }
            }
        }
    }

    vector<map<int, double>> dp(n);
    priority_queue<tuple<double, int, int>> pq;
    dp[0][n - 1] = 0;
    pq.emplace(-dp[0][n - 1], 0, n - 1);

    while (!pq.empty()) {
        auto t = pq.top();
        pq.pop();
        double val;
        int a, b;
        tie(val, a, b) = t;
        val *= -1;
        if (dp[a][b] < val) continue;
        for (int da : {-1, 0, 1}) {
            for (int db : {-1, 0, 1}) {
                int na = a + da, nb = b + db;
                if (na < 0 or n <= na or nb < 0 or n <= nb) continue;
                if (vs[na].y != vs[nb].y) continue;
                double cost = val + dist(vs[a], vs[na]) + dist(vs[b], vs[nb]);
                if (!dp[na].count(nb) or cost < dp[na][nb]) {
                    dp[na][nb] = cost;
                    pq.emplace(-cost, na, nb);
                }
            }
        }
    }

    double ans = 1e9;
    for (int i = 0; i < n; i++) {
        if (dp[i].count(i)) {
            ans = min(ans, dp[i][i]);
        }
    }

    cout << ans << '\n';
    return true;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    while (solve())
        ;
    return 0;
}
accuracy: 1
time_ms: 560
memory_kb: 9432
final_rank: 8

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (size_t i = 0; i < v.size(); i++) {
        os << v[i] << (i + 1 == v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (size_t i = 0; i < v.size(); i++) {
        os << v[i] << (i + 1 == v.size() ? "" : " ");
    }
    return os;
}
template <typename T, size_t N> ostream& operator<<(ostream& os, const array<T, N>& v) {
    for (size_t i = 0; i < N; i++) {
        os << v[i] << (i + 1 == N ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) void(0)
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }
long long MSK(int n) { return (1LL << n) - 1; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

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

template <typename T> void mkuni(vector<T>& v) {
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
}
template <typename T> int lwb(const vector<T>& v, const T& x) { return lower_bound(v.begin(), v.end(), x) - v.begin(); }
#pragma endregion

const int INF = 1e9;
const long long IINF = 1e18;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

struct vertex {
    int l, r;
    double x;
    int y, id;
    vertex(int l, int r, double x, int y, int id) : l(l), r(r), x(x), y(y), id(id) {}
};

double dist(const vertex& a, const vertex& b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }

bool solve() {
    int N;
    cin >> N;
    if (N == 0) return false;
    vector<int> x(N), y(N);
    for (int i = 0; i < N; i++) cin >> x[i] >> y[i];

    vector<int> ys = y;
    sort(ys.begin(), ys.end());
    ys.erase(unique(ys.begin(), ys.end()), ys.end());
    vector<vertex> vs;
    int sz = ys.size(), n = 0;
    for (int i = 0; i < N; i++) {
        vs.emplace_back(i, i, x[i], y[i], n++);
        if (i == N - 1) break;
        double d = double(x[i + 1] - x[i]) / abs(y[i + 1] - y[i]);
        if (y[i] < y[i + 1]) {
            for (int j = 0; j < sz; j++) {
                if (y[i] < ys[j] and ys[j] < y[i + 1]) {
                    vs.emplace_back(i, i + 1, x[i] + d * (ys[j] - y[i]), ys[j], n++);
                }
            }
        } else {
            for (int j = sz - 1; j >= 0; j--) {
                if (ys[j] < y[i] and y[i + 1] < ys[j]) {
                    vs.emplace_back(i, i + 1, x[i] + d * (y[i] - ys[j]), ys[j], n++);
                }
            }
        }
    }

    vector<map<int, double>> dp(n);
    priority_queue<tuple<double, int, int>> pq;
    dp[0][n - 1] = 0;
    pq.emplace(-dp[0][n - 1], 0, n - 1);

    while (!pq.empty()) {
        auto t = pq.top();
        pq.pop();
        double val;
        int a, b;
        tie(val, a, b) = t;
        val *= -1;
        if (dp[a][b] < val) continue;
        for (int da : {-1, 0, 1}) {
            for (int db : {-1, 0, 1}) {
                int na = a + da, nb = b + db;
                if (na < 0 or n <= na or nb < 0 or n <= nb) continue;
                if (vs[na].y != vs[nb].y) continue;
                double cost = val + dist(vs[a], vs[na]) + dist(vs[b], vs[nb]);
                if (!dp[na].count(nb) or cost < dp[na][nb]) {
                    dp[na][nb] = cost;
                    pq.emplace(-cost, na, nb);
                }
            }
        }
    }

    double ans = 1e9;
    for (int i = 0; i < n; i++) {
        if (dp[i].count(i)) {
            ans = min(ans, dp[i][i]);
        }
    }

    cout << ans << '\n';
    return true;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    while (solve())
        ;
    return 0;
}
accuracy: 1
time_ms: 570
memory_kb: 9544
final_rank: 9

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/mincostflow>
//using namespace atcoder;
//const int mod = 1e9 + 7;
const int mod = 998244353;

bool in(ll y, ll x, ll h, ll w){
    return 0 <= y && y < h && 0 <= x && x < w;
}

using tu = tuple<double,int,int>;

int main(){
    while(1){
        int n; cin >> n;
        if(!n) break;
        vl x(n),y(n);
        set<int> se;
        rep(i,n) cin >> x[i] >> y[i], se.insert(y[i]);
        vd X;
        vl Y;
        rep(i,n){
            X.push_back(x[i]); Y.push_back(y[i]);
            if(i == n-1) break;
            int sgn = y[i+1]>y[i] ? 1 : -1;
            double dx = y[i+1]==y[i] ? 0 : (double)(x[i+1]-x[i]) / abs(y[i+1]-y[i]);
            for(int j=1; j<abs(y[i+1]-y[i]); j++){
                if(!se.count(y[i]+sgn*j)) continue;
                X.push_back(x[i]+dx*j);
                Y.push_back(y[i]+sgn*j);
            }
        }
        int N = X.size();
        map<pii,double> dp;
        priority_queue<tu,vector<tu>,greater<tu>> pq;
        dp[{0,N-1}] = 0;
        pq.emplace(0,0,N-1);
        auto dist = [&](double x1, int y1, double x2, int y2) -> double {
            return sqrt((y1-y2)*(y1-y2) + (x1-x2)*(x1-x2));
        };
        while(!pq.empty()){
            ll d,l,r;
            tie(d,l,r) = pq.top(); pq.pop();
            int cy = Y[l];
            double cxl = X[l], cxr = X[r];
            for(int i=l-1; i<=l+1; i++) for(int j=r-1; j<=r+1; j++){
                if(i<0||i>=N||j<0||j>=N) continue;
                if(i>j) continue;
                if(Y[i] != Y[j]) continue;
                double cost = dist(cxl,cy,X[i],Y[i]) + dist(cxr,cy,X[j],Y[j]);
                if(!dp.count({i,j})) dp[{i,j}] = dp[{l,r}] + cost, pq.emplace(dp[{i,j}],i,j);
                else if(chmin(dp[{i,j}], dp[{l,r}] + cost)) pq.emplace(dp[{i,j}],i,j); 
            }
        }
        double ans = inf;
        rep(i,N) if(dp.count({i,i})) chmin(ans, dp[{i,i}]);
        printf("%.10f\n",ans);
    }
}
accuracy: 1
time_ms: 1000
memory_kb: 6220
final_rank: 13

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}

double solve(int n){
    double res = 1e18;
    vector<int> x(n),y(n);
    vector<int> v;
    for(int i=0;i<n;i++){
        cin >> x[i] >> y[i];
    }
    v = y;
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()),v.end());
    vector<pair<double,int>> point;
    point.push_back({x[0],y[0]});
    int j = 0;
    for(int i=0;i+1<n;i++){
        int ad;
        if(y[i] < y[i+1]){
            ad = 1;
        }
        else if(y[i] > y[i+1]){
            ad = -1;
        }
        else{
            point.push_back({x[i+1],y[i+1]});
            continue;
        }
        while(y[i+1]!=v[j]){
            j+=ad;
            double nx = x[i];
            nx += (double)(x[i+1]-x[i]) * (double)abs(v[j]-y[i]) / (double)abs(y[i]-y[i+1]);
            point.push_back({nx,v[j]});
        }
    }
    n = point.size();
    vector<vector<bool>> dp(n,vector<bool>(n));
    priority_queue<pair<double,pair<int,int>>,vector<pair<double,pair<int,int>>>,greater<pair<double,pair<int,int>>>> pq;
    pq.push({0,{0,n-1}});
    while(pq.size()){
        auto p = pq.top(); pq.pop();
        int s = p.second.first, t = p.second.second;
        if(t == s){
            res = p.first;
            break;
        }
        if(dp[s][t])continue;
        dp[s][t] = 1; 
        for(int i=-1;i<=1;i++){
            for(int j=-1;j<=1;j++){
                int si = s+i;
                int ti = t+j;
                if(0<=si and si<n and 0<=ti and ti<n and point[si].second == point[ti].second and !dp[si][ti]){
                    double cost = p.first 
                    + sqrt((point[s].first-point[si].first)*(point[s].first-point[si].first) + (point[s].second-point[si].second)*(point[s].second-point[si].second))
                    + sqrt((point[t].first-point[ti].first)*(point[t].first-point[ti].first) + (point[t].second-point[ti].second)*(point[t].second-point[ti].second));
                    pq.push({cost,{si,ti}});
                }
            }
        }
    }
    return res;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n;
    while(cin >> n,n){
        printf("%.9f\n",solve(n));
    }
}
accuracy: 1
time_ms: 40
memory_kb: 6416
final_rank: 3

code_snippet: #include<iostream>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
int N;
double dp[5050][5050];
main()
{
	while(cin>>N,N)
	{
		vector<pair<int,int> >A(N);
		vector<int>hs(N);
		for(int i=0;i<N;i++)
		{
			cin>>A[i].first>>A[i].second;
			hs[i]=A[i].second;
		}
		sort(hs.begin(),hs.end());
		hs.erase(unique(hs.begin(),hs.end()),hs.end());
		vector<pair<double,int> >X;
		X.push_back(A[0]);
		for(int i=1;i<N;i++)
		{
			int dx=A[i].first-A[i-1].first;
			int dy=A[i].second-A[i-1].second;
			if(dy==0)
			{
				X.push_back(A[i]);
			}
			else if(dy>0)
			{
				int lo=lower_bound(hs.begin(),hs.end(),A[i-1].second)-hs.begin();
				int hi=lower_bound(hs.begin(),hs.end(),A[i].second)-hs.begin();
				for(int j=lo+1;j<=hi;j++)
				{
					int ny=hs[j]-A[i-1].second;
					X.push_back(make_pair(A[i-1].first+dx*ny/(double)dy,hs[j]));
				}
			}
			else
			{
				int hi=lower_bound(hs.begin(),hs.end(),A[i-1].second)-hs.begin();
				int lo=lower_bound(hs.begin(),hs.end(),A[i].second)-hs.begin();
				for(int j=hi-1;j>=lo;j--)
				{
					int ny=hs[j]-A[i-1].second;
					X.push_back(make_pair(A[i-1].first+dx*ny/(double)dy,hs[j]));
				}
			}
		}
		N=X.size();
		for(int i=0;i<N;i++)for(int j=i;j<N;j++)dp[i][j]=1e150;
		dp[0][N-1]=0;
		priority_queue<pair<double,pair<int,int> > >P;
		P.push(make_pair(0,make_pair(0,N-1)));
		while(!P.empty())
		{
			int i=P.top().second.first,j=P.top().second.second;
			double cost=-P.top().first;
			P.pop();
			if(i==j)continue;
			//if(i==j||dp[i][j]<cost)continue;
			int dyi=X[i+1].second-X[i].second;
			int dyj=X[j-1].second-X[j].second;
			if(dyi==0)
			{
				double nxt=cost+X[i+1].first-X[i].first;
				if(dp[i+1][j]>nxt)
				{
					dp[i+1][j]=nxt;
					P.push(make_pair(-nxt,make_pair(i+1,j)));
				}
			}
			if(dyj==0)
			{
				double nxt=cost+X[j].first-X[j-1].first;
				if(dp[i][j-1]>nxt)
				{
					dp[i][j-1]=nxt;
					P.push(make_pair(-nxt,make_pair(i,j-1)));
				}
			}
			if(dyi==dyj)
			{
				double nxt=cost+hypot(X[i+1].first-X[i].first,dyi)+hypot(X[j].first-X[j-1].first,dyj);
				if(dp[i+1][j-1]>nxt)
				{
					dp[i+1][j-1]=nxt;
					P.push(make_pair(-nxt,make_pair(i+1,j-1)));
				}
			}
			if(j<N-1)
			{
				int ndyj=X[j+1].second-X[j].second;
				if(ndyj==0)
				{
					double nxt=cost+X[j+1].first-X[j].first;
					if(dp[i][j+1]>nxt)
					{
						dp[i][j+1]=nxt;
						P.push(make_pair(-nxt,make_pair(i,j+1)));
					}
				}
				else if(dyi==ndyj)
				{
					double nxt=cost+hypot(X[i+1].first-X[i].first,dyi)+hypot(X[j+1].first-X[j].first,ndyj);
					if(dp[i+1][j+1]>nxt)
					{
						dp[i+1][j+1]=nxt;
						P.push(make_pair(-nxt,make_pair(i+1,j+1)));
					}
				}
			}
			if(i>0)
			{
				int ndyi=X[i-1].second-X[i].second;
				if(ndyi==0)
				{
					double nxt=cost+X[i].first-X[i-1].first;
					if(dp[i-1][j]>nxt)
					{
						dp[i-1][j]=nxt;
						P.push(make_pair(-nxt,make_pair(i-1,j)));
					}
				}
				else if(ndyi==dyj)
				{
					double nxt=cost+hypot(X[i].first-X[i-1].first,ndyi)+hypot(X[j].first-X[j-1].first,dyj);
					if(dp[i-1][j-1]>nxt)
					{
						dp[i-1][j-1]=nxt;
						P.push(make_pair(-nxt,make_pair(i-1,j-1)));
					}
				}
			}
			if(i>0&&j<N-1)
			{
				int ndyi=X[i-1].second-X[i].second;
				int ndyj=X[j+1].second-X[j].second;
				if(ndyi==ndyj)
				{
					double nxt=cost+hypot(X[i].first-X[i-1].first,ndyi)+hypot(X[j+1].first-X[j].first,ndyj);
					if(dp[i-1][j+1]>nxt)
					{
						dp[i-1][j+1]=nxt;
						P.push(make_pair(-nxt,make_pair(i-1,j+1)));
					}
				}
			}
		}
		double ans=1e150;
		for(int i=0;i<N;i++)ans=min(ans,dp[i][i]);
		cout<<fixed<<setprecision(16)<<ans<<endl;
	}
}
accuracy: 1
time_ms: 530
memory_kb: 116280
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define POPCOUNT(x) __builtin_popcount(x)
template <typename T> void chmin(T &a, const T &b) { a = min(a, b); }
template <typename T> void chmax(T &a, const T &b) { a = max(a, b); }

const ll INF = 1LL << 60;

struct FastIO {
    FastIO() {
        cin.tie(0);
        ios::sync_with_stdio(0);
    }
} fastiofastio;

using State = tuple<double, int, int, int>;
using P = pair<int, double>;

double dist[100][100][1000];
int x[100], y[100];
int N;

int main() {
    while (1) {
        cin >> N;
        if (N == 0)
            break;
        for (int i = 0; i < N; i++)
            cin >> x[i] >> y[i];
        fill((double *)dist, (double *)(dist + N), 1e9);
        dist[0][N - 1][0] = 0;
        priority_queue<State, vector<State>, greater<State>> que;
        que.emplace(0, 0, N - 1, 0);
        while (!que.empty()) {
            State now = que.top();
            que.pop();
            double d = get<0>(now);
            int A = get<1>(now);
            int B = get<2>(now);
            int H = get<3>(now);
            if (dist[A][B][H] < d)
                continue;
            if (A == N - 1 || B == 0)
                continue;
            vector<P> upA;
            if (y[A] > H || y[A + 1] > H) {
                double X = x[A + 1] - x[A];
                double Y = abs(y[A + 1] - y[A]);
                if (y[A + 1] == H + 1)
                    upA.emplace_back(A + 1, sqrt(1 + pow(X / Y, 2)));
                else
                    upA.emplace_back(A, sqrt(1 + pow(X / Y, 2)));
            }
            if (A > 0 && y[A] == H && y[A - 1] > H) {
                double X = x[A] - x[A - 1];
                double Y = y[A] - y[A - 1];
                upA.emplace_back(A - 1, sqrt(1 + pow(X / Y, 2)));
            }
            vector<P> upB;
            if (y[B] > H || y[B - 1] > H) {
                double X = x[B] - x[B - 1];
                double Y = abs(y[B] - y[B - 1]);
                if (y[B - 1] == H + 1)
                    upB.emplace_back(B - 1, sqrt(1 + pow(X / Y, 2)));
                else
                    upB.emplace_back(B, sqrt(1 + pow(X / Y, 2)));
            }
            if (B + 1 < N && y[B] == H && y[B + 1] > H) {
                double X = x[B + 1] - x[B];
                double Y = y[B + 1] - y[B];
                upB.emplace_back(B + 1, sqrt(1 + pow(X / Y, 2)));
            }
            vector<P> downA;
            if (y[A] < H || y[A + 1] < H) {
                double X = x[A + 1] - x[A];
                double Y = abs(y[A + 1] - y[A]);
                if (y[A + 1] == H - 1)
                    downA.emplace_back(A + 1, sqrt(1 + pow(X / Y, 2)));
                else
                    downA.emplace_back(A, sqrt(1 + pow(X / Y, 2)));
            }
            if (A > 0 && y[A] == H && y[A - 1] < H) {
                double X = x[A] - x[A - 1];
                double Y = y[A] - y[A - 1];
                downA.emplace_back(A - 1, sqrt(1 + pow(X / Y, 2)));
            }
            vector<P> downB;
            if (y[B] < H || y[B - 1] < H) {
                double X = x[B] - x[B - 1];
                double Y = abs(y[B] - y[B - 1]);
                if (y[B - 1] == H - 1)
                    downB.emplace_back(B - 1, sqrt(1 + pow(X / Y, 2)));
                else
                    downB.emplace_back(B, sqrt(1 + pow(X / Y, 2)));
            }
            if (B + 1 < N && y[B] == H && y[B + 1] < H) {
                double X = x[B + 1] - x[B];
                double Y = y[B + 1] - y[B];
                downB.emplace_back(B + 1, sqrt(1 + pow(X / Y, 2)));
            }
            for (P p1 : upA) {
                for (P p2 : upB) {
                    if (dist[p1.first][p2.first][H + 1] >
                        d + p1.second + p2.second) {
                        dist[p1.first][p2.first][H + 1] =
                            d + p1.second + p2.second;
                        que.emplace(dist[p1.first][p2.first][H + 1], p1.first,
                                    p2.first, H + 1);
                    }
                }
            }
            for (P p1 : downA) {
                for (P p2 : downB) {
                    if (dist[p1.first][p2.first][H - 1] >
                        d + p1.second + p2.second) {
                        dist[p1.first][p2.first][H - 1] =
                            d + p1.second + p2.second;
                        que.emplace(dist[p1.first][p2.first][H - 1], p1.first,
                                    p2.first, H - 1);
                    }
                }
            }
            if (A > 0 && y[A] == H && y[A - 1] == H) {
                double len = x[A] - x[A - 1];
                if (dist[A - 1][B][H] > d + len) {
                    dist[A - 1][B][H] = d + len;
                    que.emplace(dist[A - 1][B][H], A - 1, B, H);
                }
            }
            if (y[A + 1] == H) {
                double len = x[A + 1] - x[A];
                if (dist[A + 1][B][H] > d + len) {
                    dist[A + 1][B][H] = d + len;
                    que.emplace(dist[A + 1][B][H], A + 1, B, H);
                }
            }
            if (B + 1 < N && y[B] == H && y[B + 1] == H) {
                double len = x[B + 1] - x[B];
                if (dist[A][B + 1][H] > d + len) {
                    dist[A][B + 1][H] = d + len;
                    que.emplace(dist[A][B + 1][H], A, B + 1, H);
                }
            }
            if (y[B - 1] == H) {
                double len = x[B] - x[B - 1];
                if (dist[A][B - 1][H] > d + len) {
                    dist[A][B - 1][H] = d + len;
                    que.emplace(dist[A][B - 1][H], A, B - 1, H);
                }
            }
        }
        double ans = 1e9;
        for (int i = 1; i + 1 < N; i++) {
            ans = min(ans, dist[i][i][y[i]]);
        }
        for (int i = 0; i + 1 < N; i++) {
            if (y[i] == y[i + 1]) {
                ans = min(ans, dist[i][i + 1][y[i]] + (x[i + 1] - x[i]));
            }
        }
        cout << fixed << setprecision(15) << ans << endl;
    }
}
accuracy: 1
time_ms: 3640
memory_kb: 81648
final_rank: 20

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-9;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

struct Node {
	int l, r;
	long double cost;
	Node(const int ll, const int rr, const long double cc) {
		l = ll, r = rr, cost = cc;
	}
	bool operator<(const Node&n)const {
		return cost > n.cost;
	}
};

struct Point {
	long double x, y;
	Point(const long double xx, const long double yy) {
		x = xx, y = yy;
	}
	bool operator<(const Point&p)const {
		return x < p.x;
	}
};

vector<Point>func() {
	vector<long double>x(N);
	vector<long double>y(N);
	set<int>st;
	for (int i = 0; i < N; i++) {
		cin >> x[i] >> y[i];
		st.insert(y[i]);
	}
	vector<Point>ret;
	for (int i = 0; i < N; i++) {
		ret.push_back(Point(x[i], y[i]));
	}
	for (int i = 1; i < N; i++) {
		for (auto j : st) {
			if (y[i] > j&&j > y[i - 1]) {
				ret.push_back(Point(x[i] + (y[i] - j) / (y[i] - y[i - 1])*(x[i - 1] - x[i]), j));
			}
			if (y[i] < j&&j < y[i - 1]) {
				ret.push_back(Point(x[i] + (y[i] - j) / (y[i] - y[i - 1])*(x[i - 1] - x[i]), j));
			}
		}
	}
	sort(ret.begin(), ret.end());
	return ret;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	while (cin >> N, N) {
		auto p = func();
		long double ans = MOD;
		//vector<vector<long double>>dp(p.size(), vector<long double>(p.size(), MOD));
		vector<unordered_map<int, long double>>dp(p.size());
		priority_queue<Node>PQ;
		PQ.push(Node(0, p.size() - 1, 0));
		while (!PQ.empty()) {
			auto box = PQ.top();
			PQ.pop();
			for (int i = box.l - 1; i <= box.l + 1; i++) {
				if (i < 0 || i >= p.size())continue;
				for (int j = box.r - 1; j <= box.r + 1; j++) {
					if (j < 0 || j >= p.size())continue;
					if (p[i].y != p[j].y)continue;
					long double add = hypot(p[i].x - p[box.l].x, p[i].y - p[box.l].y) + hypot(p[j].x - p[box.r].x, p[j].y - p[box.r].y);
					if (dp[i].find(j) == dp[i].end()) {
						dp[i][j] = box.cost + add;
						PQ.push(Node(i, j, dp[i][j]));
					}
					else if (dp[i][j] > box.cost + add) {
						dp[i][j] = box.cost + add;
						PQ.push(Node(i, j, dp[i][j]));
					}
				}
			}
		}
		for (int i = 0; i < dp.size(); i++) {
			if(dp[i].find(i)!=dp[i].end())ans = min(ans, dp[i][i]);
		}
		cout << fixed << setprecision(20) << ans << endl;
	}
}
accuracy: 1
time_ms: 1410
memory_kb: 10512
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
int main(){
  cout << fixed << setprecision(10);
  while (1){
    int N;
    cin >> N;
    if (N == 0){
      break;
    }
    vector<int> x(N), y(N);
    for (int i = 0; i < N; i++){
      cin >> x[i] >> y[i];
    }
    vector<int> h = y;
    sort(h.begin(), h.end());
    h.erase(unique(h.begin(), h.end()), h.end());
    vector<double> x2;
    vector<int> y2;
    x2.push_back(x[0]);
    y2.push_back(y[0]);
    int M = 1;
    for (int i = 1; i < N; i++){
      auto itr1 = lower_bound(h.begin(), h.end(), y[i - 1]);
      auto itr2 = lower_bound(h.begin(), h.end(), y[i]);
      if (itr1 < itr2){
        itr1++;
        while (itr1 < itr2){
          x2.push_back(x[i - 1] + (double) (x[i] - x[i - 1]) * (*itr1 - y[i - 1]) / (y[i] - y[i - 1]));
          y2.push_back(*itr1);
          M++;
          itr1++;
        }
      }
      if (itr1 > itr2){
        itr1--;
        while (itr1 > itr2){
          x2.push_back(x[i - 1] + (double) (x[i] - x[i - 1]) * (y[i - 1] - *itr1) / (y[i - 1] - y[i]));
          y2.push_back(*itr1);
          M++;
          itr1--;
        }
      }
      x2.push_back(x[i]);
      y2.push_back(y[i]);
      M++;
    }
    vector<double> d(M - 1);
    for (int i = 0; i < M - 1; i++){
      d[i] = sqrt(pow(x2[i + 1] - x2[i], 2) + pow(y2[i + 1] - y2[i], 2));
    }
    vector<vector<bool>> used(M, vector<bool>(M, false));
    priority_queue<pair<double, pair<int, int>>, vector<pair<double, pair<int, int>>>, greater<pair<double, pair<int, int>>>> pq;
    pq.push(make_pair(0, make_pair(0, M - 1)));
    double ans = -1;
    while (!pq.empty()){
      double s = pq.top().first;
      int a = pq.top().second.first;
      int b = pq.top().second.second;
      pq.pop();
      if (a == b){
        ans = s;
        break;
      }
      if (!used[a][b]){
        used[a][b] = true;
        for (int da = -1; da <= 1; da++){
          for (int db = -1; db <= 1; db++){
            int a2 = a + da;
            int b2 = b + db;
            if (0 <= a2 && a2 < M && 0 <= b2 && b2 < M){
              if (y2[a2] == y2[b2] && !used[a2][b2]){
                double s2 = s;
                if (a != a2){
                  s2 += d[min(a, a2)];
                }
                if (b != b2){
                  s2 += d[min(b, b2)];
                }
                pq.push(make_pair(s2, make_pair(a2, b2)));
              }
            }
          }
        }
      }
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 40
memory_kb: 6428
final_rank: 4

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define SZ(x) (int)(x.size())
#define REP(i, n) for(int i=0;i<(n);++i)
#define FOR(i, a, b) for(int i=(a);i<(b);++i)
#define RREP(i, n) for(int i=(int)(n);i>=0;--i)
#define RFOR(i, a, b) for(int i=(int)(a);i>=(int)(b);--i)
#define ALL(a) (a).begin(),(a).end()
#define DUMP(x) cerr<<#x<<" = "<<(x)<<endl
#define DEBUG(x) cerr<<#x<<" = "<<(x)<<" (L"<<__LINE__<<")"<< endl;

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using P = pair<int, int>;

const double eps = 1e-8;
const ll MOD = 1000000007;
const int INF = INT_MAX / 2;
const ll LINF = LLONG_MAX / 2;

template <typename T1, typename T2>
bool chmax(T1 &a, const T2 &b) {
  if(a < b) {a = b; return true;}
  return false;
}

template <typename T1, typename T2>
bool chmin(T1 &a, const T2 &b) {
  if(a > b) {a = b; return true;}
  return false;
}

template<typename T1, typename T2>
ostream& operator<<(ostream &os, const pair<T1, T2> p) {
  os << p.first << ":" << p.second;
  return os;
}

template<class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  REP(i, SZ(v)) {
    if(i) os << " ";
    os << v[i];
  }
  return os;
}

double cross(double x1, double y1, double x2, double y2, double y) {
  if(abs(y1 - y) < eps || abs(y2 - y) < eps) return -1;
  if(!((y1 < y && y < y2) || (y2 < y && y < y1))) {
    return -1;
  }

  return x1 + (x2 - x1) * (y - y1) / (y2 - y1);
}

double kyori(pair<double, double> p1, pair<double, double> p2) {
  return sqrt((p1.first - p2.first) * (p1.first - p2.first) + (p1.second - p2.second) * (p1.second - p2.second));
}

bool solve() {
  int n; cin >> n;
  if(n == 0) return false;
  vi x(n), y(n);
  int ma = 0;
  set<int> sty;
  REP(i, n) {
    cin >> x[i] >> y[i];
    chmax(ma, y[i]);
    sty.insert(y[i]);
  }


  vector<pair<double, double>> v;
  REP(i, n) {
    v.emplace_back(x[i], y[i]);
  }
  for(auto &e: sty) {
    REP(i, n-1) {
      double nowx = cross(x[i], y[i], x[i+1], y[i+1], e);
      if(abs(nowx + 1) < eps) continue;
      v.emplace_back(nowx, e);
    }
  }
  sty.clear();
  sort(ALL(v));
  int sz = SZ(v);
  vector<map<int, double>> d(sz);
  using elm = pair<double, pair<int, int>>;
  priority_queue<elm, vector<elm>, greater<elm>> pq;

  d[0][sz-1] = 0.0;
  pq.push({0.0, {0, sz-1}});
  double ans = INF;
  while(!pq.empty()) {
    auto now = pq.top(); pq.pop();
    double dist = now.first;
    int i1 = now.second.first;
    int i2 = now.second.second;
    if(i1 == i2) {
      ans = dist;
      break;
    }

    //cout << d[i1][i2] << " " << v[i1] << " " << v[i2] << endl;

    double nowy = v[i1].second;

    vector<bool> same(4);

    if(i1 != 0 && abs(nowy - v[i1-1].second) < eps) {
      if(d[i1-1].find(i2) == d[i1-1].end() || d[i1-1][i2] > d[i1][i2] + kyori(v[i1-1], v[i1])) {
        d[i1-1][i2] = d[i1][i2] + kyori(v[i1-1], v[i1]);
        pq.push({d[i1-1][i2], {i1-1, i2}});
      }
      same[0] = true;
    }

    if(i1 != sz-1 && abs(nowy - v[i1+1].second) < eps) {
      if(d[i1+1].find(i2) == d[i1+1].end() || d[i1+1][i2] > d[i1][i2] + kyori(v[i1+1], v[i1])) {
        d[i1+1][i2] = d[i1][i2] + kyori(v[i1+1], v[i1]);
        pq.push({d[i1+1][i2], {i1+1, i2}});
      }
      same[1] = true;
    }

    if(i1 != 0 && abs(nowy - v[i2-1].second) < eps) {
      if(d[i1].find(i2-1) == d[i1].end() || d[i1][i2-1] > d[i1][i2] + kyori(v[i2-1], v[i2])) {
        d[i1][i2-1] = d[i1][i2] + kyori(v[i2-1], v[i2]);
        pq.push({d[i1][i2-1], {i1, i2-1}});
      }
      same[2] = true;
    }

    if(i1 != 0 && abs(nowy - v[i2+1].second) < eps) {
      if(d[i1].find(i2+1) == d[i1].end() || d[i1][i2+1] > d[i1][i2] + kyori(v[i2+1], v[i2])) {
        d[i1][i2+1] = d[i1][i2] + kyori(v[i2+1], v[i2]);
        pq.push({d[i1][i2+1], {i1, i2+1}});
      }
      same[3] = true;
    }



    if(i1 != 0 && i2 != 0 && v[i1-1].second < nowy == v[i2-1].second < nowy && !same[0] && !same[2]) {
      double diff = 0.0;
      diff += kyori(v[i1], v[i1-1]);
      diff += kyori(v[i2], v[i2-1]);
      if(d[i1-1].find(i2-1) == d[i1-1].end() || d[i1-1][i2-1] > d[i1][i2] + diff) {
        d[i1-1][i2-1] = d[i1][i2] + diff;
        pq.push({d[i1-1][i2-1], {i1-1, i2-1}});
      }
    }

    if(i1 != 0 && i2 != sz-1 && v[i1-1].second < nowy == v[i2+1].second < nowy && !same[0] && !same[3]) {
      double diff = 0.0;
      diff += kyori(v[i1], v[i1-1]);
      diff += kyori(v[i2], v[i2+1]);
      if(d[i1-1].find(i2+1) == d[i1-1].end() || d[i1-1][i2+1] > d[i1][i2] + diff) {
        d[i1-1][i2+1] = d[i1][i2] + diff;
        pq.push({d[i1-1][i2+1], {i1-1, i2+1}});
      }
    }

    if(i1 != sz-1 && i2 != 0 && v[i1+1].second < nowy == v[i2-1].second < nowy && !same[1] && !same[2] ) {
      double diff = 0.0;
      diff += kyori(v[i1], v[i1+1]);
      diff += kyori(v[i2], v[i2-1]);
      if(d[i1+1].find(i2-1) == d[i1+1].end() || d[i1+1][i2-1] > d[i1][i2] + diff) {
        d[i1+1][i2-1] = d[i1][i2] + diff;
        pq.push({d[i1+1][i2-1], {i1+1, i2-1}});
      }
    }

    if(i1 != sz-1 && i2 != sz-1 && v[i1+1].second < nowy == v[i2+1].second < nowy && !same[1] && !same[3]) {
      double diff = 0.0;
      diff += kyori(v[i1], v[i1+1]);
      diff += kyori(v[i2], v[i2+1]);
      if(d[i1+1].find(i2+1) == d[i1+1].end() || d[i1+1][i2+1] > d[i1][i2] + diff) {
        d[i1+1][i2+1] = d[i1][i2] + diff;
        pq.push({d[i1+1][i2+1], {i1+1, i2+1}});
      }
    }
  }

  /*
  double ans = INF;
  REP(i, sz) {
    if(abs(d[i][i] - INF) > eps) chmin(ans, d[i][i]);
  }
   */
  cout << ans << endl;

  return true;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(10);

  while(solve()) {}

  return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 5860
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=5005,INF=1<<30;
int id=0;
double x[MAX],y[MAX],dis[MAX][MAX];

void dijkstra(){
    for(int i=0;i<id;i++) for(int j=i;j<id;j++) dis[i][j]=INF;
    dis[0][id-1]=0;
    priority_queue<pair<double,pair<int,int>>,vector<pair<double,pair<int,int>>>,greater<pair<double,pair<int,int>>>> PQ;
    PQ.push(mp(0,mp(0,id-1)));
    
    while(!PQ.empty()){
        auto u=PQ.top();PQ.pop();
        if(u.se.fi==u.se.se) break;
        
        double d=dis[u.se.fi][u.se.se];
        
        if(u.fi>d) continue;
        
        for(int a=-1;a<=1;a++){
            for(int b=-1;b<=1;b++){
                if(a==0&&b==0) continue;
                
                if(u.se.fi+a<0||u.se.fi+a>=id||u.se.se+b<0||u.se.se+b>=id) continue;
                
                int toa=u.se.fi+a,tob=u.se.se+b;
                
                if(y[toa]==y[tob]){
                    if(chmin(dis[toa][tob],d+hypot(x[toa-a]-x[toa],y[toa-a]-y[toa])+hypot(x[tob-b]-x[tob],y[tob-b]-y[tob]))){
                        PQ.push(mp(dis[toa][tob],mp(toa,tob)));
                    }
                }
            }
        }
    }
    
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    while(1){
        int N;cin>>N;
        if(N==0) break;
        memset(x,0,sizeof(x));
        memset(y,0,sizeof(y));
        vector<double> px,py;
        set<double> se,se2;
        for(int i=0;i<N;i++){
            double a,b;cin>>a>>b;
            px.push_back(a);
            py.push_back(b);
            se.insert(b);
            se2.insert(-b);
        }
        
        if(N==2){
            cout<<px[1]<<endl;
            continue;
        }
        
        id=0;
        
        for(int i=0;i+1<N;i++){
            if(py[i]<py[i+1]){
                for(double yy:se){
                    if(py[i]<=yy&&yy<=py[i+1]){
                        if(yy==py[i+1]&&i+1!=N-1) continue;
                        double d=(abs(yy-py[i])/abs(py[i+1]-py[i])*(px[i+1]-px[i])+px[i]);
                        x[id]=d;
                        y[id]=yy;
                        id++;
                    }
                }
            }else if(py[i]==py[i+1]){
                x[id]=px[i];
                y[id]=py[i];
                id++;
                
                if(i+1==N-1){
                    x[id]=px[i+1];
                    y[id]=py[i+1];
                    id++;
                }
            }else{
                for(double yy2:se2){
                    double yy=-yy2;
                    if(py[i]>=yy&&yy>=py[i+1]){
                        if(yy==py[i+1]&&i+1!=N-1) continue;
                        double d=(abs(yy-py[i])/abs(py[i+1]-py[i])*(px[i+1]-px[i])+px[i]);
                        x[id]=d;
                        y[id]=yy;
                        id++;
                    }
                }
            }
        }
        
        dijkstra();
        
        double ans=INF;
        for(int i=0;i<id;i++) chmin(ans,dis[i][i]);
        
        cout<<setprecision(25)<<ans<<endl;
    }
    
}
accuracy: 1
time_ms: 530
memory_kb: 116016
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=5005,INF=1<<30;
int id=0;
double x[MAX],y[MAX],dis[MAX][MAX];

void dijkstra(){
    for(int i=0;i<id;i++) for(int j=0;j<=i;j++) dis[i][j]=INF;
    dis[id-1][0]=0;
    priority_queue<pair<double,pair<int,int>>,vector<pair<double,pair<int,int>>>,greater<pair<double,pair<int,int>>>> PQ;
    PQ.push(mp(0,mp(0,id-1)));
    
    while(!PQ.empty()){
        auto u=PQ.top();PQ.pop();
        if(u.se.fi==u.se.se) break;
        
        double d=dis[u.se.se][u.se.fi];
        
        if(u.fi>d) continue;
        
        for(int a=-1;a<=1;a++){
            for(int b=-1;b<=1;b++){
                if(a==0&&b==0) continue;
                
                if(u.se.fi+a<0||u.se.fi+a>=id||u.se.se+b<0||u.se.se+b>=id) continue;
                
                int toa=u.se.fi+a,tob=u.se.se+b;
                
                if(y[toa]==y[tob]){
                    if(chmin(dis[tob][toa],d+hypot(x[toa-a]-x[toa],y[toa-a]-y[toa])+hypot(x[tob-b]-x[tob],y[tob-b]-y[tob]))){
                        PQ.push(mp(dis[tob][toa],mp(toa,tob)));
                    }
                }
            }
        }
    }
    
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    while(1){
        int N;cin>>N;
        if(N==0) break;
        memset(x,0,sizeof(x));
        memset(y,0,sizeof(y));
        vector<double> px,py;
        set<double> se,se2;
        for(int i=0;i<N;i++){
            double a,b;cin>>a>>b;
            px.push_back(a);
            py.push_back(b);
            se.insert(b);
            se2.insert(-b);
        }
        
        if(N==2){
            cout<<px[1]<<endl;
            continue;
        }
        
        id=0;
        
        for(int i=0;i+1<N;i++){
            if(py[i]<py[i+1]){
                for(double yy:se){
                    if(py[i]<=yy&&yy<=py[i+1]){
                        if(yy==py[i+1]&&i+1!=N-1) continue;
                        double d=(abs(yy-py[i])/abs(py[i+1]-py[i])*(px[i+1]-px[i])+px[i]);
                        x[id]=d;
                        y[id]=yy;
                        id++;
                    }
                }
            }else if(py[i]==py[i+1]){
                x[id]=px[i];
                y[id]=py[i];
                id++;
                
                if(i+1==N-1){
                    x[id]=px[i+1];
                    y[id]=py[i+1];
                    id++;
                }
            }else{
                for(double yy2:se2){
                    double yy=-yy2;
                    if(py[i]>=yy&&yy>=py[i+1]){
                        if(yy==py[i+1]&&i+1!=N-1) continue;
                        double d=(abs(yy-py[i])/abs(py[i+1]-py[i])*(px[i+1]-px[i])+px[i]);
                        x[id]=d;
                        y[id]=yy;
                        id++;
                    }
                }
            }
        }
        
        dijkstra();
        
        double ans=INF;
        for(int i=0;i<id;i++) chmin(ans,dis[i][i]);
        
        cout<<setprecision(25)<<ans<<endl;
    }
    
}
accuracy: 1
time_ms: 520
memory_kb: 116252
final_rank: 18