#include #include #include #include #include #include using namespace std; const double EPS = 1e-8; const double INF = 1e12; class Node{ public: int aPos, bPos, h; double c; Node(int aPos, int bPos, int h, double c) : aPos(aPos), bPos(bPos), h(h), c(c) {} bool operator < (const Node &nd) const { return c > nd.c; } }; int main(){ int n; int x[100], y[100]; int h[1001]; double len[100]; static double dist[99][99][99]; ifstream fin("E.in"); while(fin >> n, n){ double res = 0.0; vector hList; for(int i=0;i> x[i] >> y[i]; hList.push_back(y[i]); } while(n-2>=0 && y[n-2] == 0){ res += x[n-1]-x[n-2]; n--; } int s = 0; while(s+1 qu; qu.push(Node(s, n-2, h[0], res)); dist[s][n-2][h[0]] = res; res = INF; while(!qu.empty()){ Node nd = qu.top(); qu.pop(); int aPos = nd.aPos, bPos = nd.bPos, hIdx = nd.h; int hCur = hList[hIdx]; if(aPos == bPos){ printf("%.3lf\n", dist[aPos][bPos][hIdx]); break; } if(dist[aPos][bPos][hIdx]+EPS < nd.c) continue; // 同じ高さの移動 if(y[aPos] == hCur && y[aPos] == y[aPos+1]){ if(dist[aPos+1][bPos][hIdx] > nd.c+len[aPos]+EPS){ dist[aPos+1][bPos][hIdx] = nd.c+len[aPos]; qu.push(Node(aPos+1, bPos, hIdx, dist[aPos+1][bPos][hIdx])); } } if(aPos-1 >= s && y[aPos] == hCur && y[aPos] == y[aPos-1]){ if(dist[aPos-1][bPos][hIdx] > nd.c+len[aPos-1]+EPS){ dist[aPos-1][bPos][hIdx] = nd.c+len[aPos-1]; qu.push(Node(aPos-1, bPos, hIdx, dist[aPos-1][bPos][hIdx])); } } if(y[bPos] == hCur && y[bPos] == y[bPos-1]){ if(dist[aPos][bPos-1][hIdx] > nd.c+len[bPos-1]+EPS){ dist[aPos][bPos-1][hIdx] = nd.c+len[bPos-1]; qu.push(Node(aPos, bPos-1, hIdx, dist[aPos][bPos-1][hIdx])); } } if(bPos+1 < n-1 && y[bPos] == hCur && y[bPos] == y[bPos+1]){ if(dist[aPos][bPos+1][hIdx] > nd.c+len[bPos]+EPS){ dist[aPos][bPos+1][hIdx] = nd.c+len[bPos]; qu.push(Node(aPos, bPos+1, hIdx, dist[aPos][bPos+1][hIdx])); } } int aBack = aPos - (y[aPos] == hCur); int bBack = bPos - (y[bPos] == hCur); // A:前進,B:後退 if((y[aPos+1] > hCur && y[bBack] > hCur) || (y[aPos+1] < hCur && y[bBack] < hCur)){ int hNext = y[aPos+1] > hCur ? min(y[aPos+1], y[bBack]) : max(y[aPos+1], y[bBack]); int aNext = aPos + (hNext == y[aPos+1]); double aLen = len[aPos]*abs(hNext-hCur)/abs(y[aPos]-y[aPos+1]); double bLen = len[bBack]*abs(hNext-hCur)/abs(y[bBack]-y[bBack+1]); if(dist[aNext][bBack][h[hNext]] > nd.c+aLen+bLen+EPS){ dist[aNext][bBack][h[hNext]] = nd.c+aLen+bLen; qu.push(Node(aNext, bBack, h[hNext], dist[aNext][bBack][h[hNext]])); } } // A:前進, B:前進 if((y[aPos+1] > hCur && y[bPos+1] > hCur) || (y[aPos+1] < hCur && y[bPos+1] < hCur)){ int hNext = y[aPos+1] > hCur ? min(y[aPos+1], y[bPos+1]) : max(y[aPos+1], y[bPos+1]); int aNext = aPos + (hNext == y[aPos+1]); int bNext = bPos + (bPos+1 != n-1 && hNext == y[bPos+1]); double aLen = len[aPos]*abs(hNext-hCur)/abs(y[aPos]-y[aPos+1]); double bLen = len[bPos]*abs(hNext-hCur)/abs(y[bPos]-y[bPos+1]); if(dist[aNext][bNext][h[hNext]] > nd.c+aLen+bLen+EPS){ dist[aNext][bNext][h[hNext]] = nd.c+aLen+bLen; qu.push(Node(aNext, bNext, h[hNext], dist[aNext][bNext][h[hNext]])); } } // A:後退, B:前進 if(aBack >= s && ((y[aBack] > hCur && y[bPos+1] > hCur) || (y[aBack] < hCur && y[bPos+1] < hCur))){ int hNext = y[aBack] > hCur ? min(y[aBack], y[bPos+1]) : max(y[aBack], y[bPos+1]); int bNext = bPos + (bPos+1 != n-1 && hNext == y[bPos+1]); double aLen = len[aBack]*abs(hNext-hCur)/abs(y[aBack]-y[aBack+1]); double bLen = len[bPos]*abs(hNext-hCur)/abs(y[bPos]-y[bPos+1]); if(dist[aBack][bNext][h[hNext]] > nd.c+aLen+bLen+EPS){ dist[aBack][bNext][h[hNext]] = nd.c+aLen+bLen; qu.push(Node(aBack, bNext, h[hNext], dist[aBack][bNext][h[hNext]])); } } // A:後退, B:後退 if(aBack >= s && ((y[aBack] > hCur && y[bBack] > hCur) || (y[aBack] < hCur && y[bBack] < hCur))){ int hNext = y[aBack] > hCur ? min(y[aBack], y[bBack]) : max(y[aBack], y[bBack]); double aLen = len[aBack]*abs(hNext-hCur)/abs(y[aBack]-y[aBack+1]); double bLen = len[bBack]*abs(hNext-hCur)/abs(y[bBack]-y[bBack+1]); if(dist[aBack][bBack][h[hNext]] > nd.c+aLen+bLen+EPS){ dist[aBack][bBack][h[hNext]] = nd.c+aLen+bLen; qu.push(Node(aBack, bBack, h[hNext], dist[aBack][bBack][h[hNext]])); } } } } }