<|instruction|>
Solve the below problem. The solution should start with an abridged problem statement. Then key observations. Then full solution based on the observations. Then C++ and Python implementations with comments.

445. Dig or Climb
Time limit per test: 0.25 second(s)
Memory limit: 262144 kilobytes
input: standard
output: standard

Benjamin Forest VIII is a king of a country. One of his best friends Nod lives in a village far from his castle. Nod gets seriously sick and is on the verge of death. Benjamin orders his subordinate Red to bring good medicine for him as soon as possible. However, there is no road from the castle to the village. Therefore, Red needs to climb over mountains and across canyons to reach the village. He has decided to get to the village on the shortest path on a map, that is, he will move on the straight line between the castle and the village. Then his way can be considered as polyline with n points (x1, y1)... (xn, yn) as illustlated in the following figure.

Here, xi and yi are coordinates of point i. The castle is located on the point (x1, y1), and the village is located on the point (xn, yn). Red can walk with speed vw. Also, since he has a skill to cut a tunnel through a mountain horizontally, he can move strictly inside the mountain with speed vc. Your job is to write a program to find the minimum time to get to the village.
Input
The input is given in the following format: n vw vc x1 y1 ... xn yn You may assume all the following: 1 <= n <= 1000, 1 <= vw, vc <= 10, -10000 <= xi, yi <= 10000, and xi < xj for all i < j.
Output
You should print the minimum time required to get to the village in a line. Each minimum time should be given as a decimal with an arbitrary number of fractional digits and with an absolute error of at most 10-6.
Example(s)
sample input
sample output
3
2 1
0 0
50 50
100 0
70.710678

sample input
sample output
3
1 1
0 0
50 50
100 0
100.000000

sample input
sample output
3
1 2
0 0
50 50
100 0
50.000000

sample input
sample output
3
2 1
0 0
100 100
150 50
106.066017

sample input
sample output
6
1 2
0 0
50 50
100 0
150 0
200 50
250 0
150.000000

sample input
sample output
2
1 2
0 0
100 0
100.000000

<|response|>
1. Abridged Problem Statement
We have n points (x1,y1),...,(xn,yn) lying along Red's straight-line route from the castle (point 1) to the village (point n). Between these boundary points, the path alternately lies above ground (on slopes) or strictly inside mountains. Red can
- Walk along exposed slopes at speed vw, and
- Tunnel horizontally inside mountains at speed vc.
Compute the minimum time to travel from point 1 to point n along this polyline.

2. Key Observations
- Dynamic Programming: let dp[i] = minimum time to reach boundary point i.
- Two move-modes give two kinds of transitions:
  - Slope walk from i-1 to i: time = distance(i-1,i)/vw.
  - Horizontal tunnel: from some earlier boundary j to i, if the segment j->j+1 spans the same height y_i. One walks along the slope j->I at speed vw, then tunnels horizontally I->i at speed vc.
- To check a possible tunnel ending at i from j < i: the horizontal line y=y_i must lie between min(y_j,y_{j+1}) and max(y_j,y_{j+1}). Compute the intersection point I of y=y_i on segment j->j+1 by linear interpolation.
- Symmetrically, tunnels can start at i and end at a later boundary k > i; this updates dp[k] using dp[i].
- Early break: when scanning left from i, as soon as y_j <= y_i, the path has descended below y_i and no further leftward segments can contain y_i. Similarly for rightward scan.

3. Full Solution Approach
Initialize dp[0]=0 and dp[i]=inf for i>0. Process boundary points in order i=0,...,n-1:
 A. Walk transition
   if i>0,
       dp[i] = min(dp[i], dp[i-1] + dist(points[i-1],points[i]) / vw)
 B. Tunnel-in transitions (j from i-1 down to 0)
   For each j from i-1 down to 0:
     let (x_j,y_j) = point j and (x_{j+1},y_{j+1}) = point j+1
     if y_i lies between y_j and y_{j+1}:
       compute intersection I = (x_I, y_i) on segment j->j+1 by linear interpolation
       walk time d1 = distance((x_j,y_j),I) / vw
       tunnel time d2 = |x_i - x_I| / vc
       dp[i] = min(dp[i], dp[j] + d1 + d2)
     if y_j <= y_i, break the j-loop
 C. Tunnel-out transitions (k from i+1 up to n-1)
   For each k from i+1 to n-1:
     let (x_k,y_k) = point k and (x_{k-1},y_{k-1}) = point k-1
     if y_i lies between y_{k-1} and y_k:
       compute intersection I = (x_I, y_i) on segment k-1->k
       walk time d1 = distance(I,(x_k,y_k)) / vw
       tunnel time d2 = |x_I - x_i| / vc
       dp[k] = min(dp[k], dp[i] + d1 + d2)
     if y_k <= y_i, break the k-loop

Answer = dp[n-1]. Overall O(n^2), which is fine for n<=1000.

4. C++ Implementation with Detailed Comments
```cpp
#include <bits/stdc++.h>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

int n;
long double vw, vc;
vector<pair<long double, long double>> points;

void read() {
    cin >> n >> vw >> vc;
    points.resize(n);
    for(int i = 0; i < n; i++) {
        cin >> points[i];
    }
}

void solve() {
    // Red moves along the terrain polyline at walking speed vw, but may also
    // tunnel horizontally through a mountain at speed vc. We do a DP over the
    // vertices, where dp[i] is the minimum time to reach point i.
    //
    // From point i we relax along the surface to the next vertex i+1 (walking).
    // For a horizontal tunnel at height y_i we look for the points where the
    // horizontal line y = y_i crosses the polyline. Scanning leftwards over
    // segments (j, j+1) we find an entry crossing, walk from point j down to
    // that crossing, then tunnel horizontally to (x_i, y_i); scanning
    // rightwards over segments (j-1, j) we tunnel from (x_i, y_i) to a crossing
    // and walk up to point j. We stop each scan once a vertex no taller than
    // y_i is reached, since the line cannot re-enter the mountain past it.
    //
    // The horizontal crossing x is found by linear interpolation along the
    // segment; degenerate horizontal segments are handled separately. The
    // answer is dp[n-1].

    vector<long double> dp(n, 1e12);
    dp[0] = 0.0;

    for(int i = 0; i < n; i++) {
        auto [x, y] = points[i];
        if(i > 0) {
            auto [x_prev, y_prev] = points[i - 1];
            dp[i] =
                min(dp[i], dp[i - 1] + sqrt(
                                           (x - x_prev) * (x - x_prev) +
                                           (y - y_prev) * (y - y_prev)
                                       ) / vw);
        }

        for(int j = i - 1; j >= 0; j--) {
            auto [x_prev, y_prev] = points[j];
            auto [x_prev_next, y_prev_next] = points[j + 1];

            long double up = max(y_prev, y_prev_next);
            long double down = min(y_prev, y_prev_next);

            if(down <= y && y <= up) {
                long double slope_x =
                    y_prev_next == y_prev
                        ? 0.0
                        : (x_prev_next - x_prev) / (y_prev_next - y_prev);
                long double intersection_x = x_prev + slope_x * (y - y_prev);
                if(y_prev_next == y_prev) {
                    intersection_x = x_prev_next;
                }

                long double dist_intersection_to_prev = sqrt(
                    (x_prev - intersection_x) * (x_prev - intersection_x) +
                    (y_prev - y) * (y_prev - y)
                );

                dp[i] =
                    min(dp[i], dp[j] + dist_intersection_to_prev / vw +
                                   (x - intersection_x) / vc);
            }

            if(y_prev <= y) {
                break;
            }
        }

        for(int j = i + 1; j < n; j++) {
            auto [x_next, y_next] = points[j];
            auto [x_next_prev, y_next_prev] = points[j - 1];

            long double up = max(y_next, y_next_prev);
            long double down = min(y_next, y_next_prev);

            if(down <= y && y <= up) {
                long double slope_x =
                    y_next_prev == y_next
                        ? 0.0
                        : (x_next - x_next_prev) / (y_next - y_next_prev);
                long double intersection_x =
                    x_next_prev + slope_x * (y - y_next_prev);
                long double dist_intersection_to_next = sqrt(
                    (x_next - intersection_x) * (x_next - intersection_x) +
                    (y_next - y) * (y_next - y)
                );

                dp[j] =
                    min(dp[j], dp[i] + dist_intersection_to_next / vw +
                                   (intersection_x - x) / vc);
            }

            if(y_next <= y) {
                break;
            }
        }
    }

    cout << setprecision(10) << fixed << dp.back() << '\n';
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        // cout << "Case #" << test << ": ";
        solve();
    }

    return 0;
}
```

5. Python Implementation with Detailed Comments
```python
import sys
import math

def main():
    data = sys.stdin.read().strip().split()
    it = iter(data)
    n = int(next(it))
    vw = float(next(it))
    vc = float(next(it))
    pts = [(float(next(it)), float(next(it))) for _ in range(n)]

    # dp[i]: min time to reach boundary point i
    dp = [1e18] * n
    dp[0] = 0.0

    for i in range(n):
        xi, yi = pts[i]

        # 1) Walk along adjacent slope
        if i > 0:
            x0, y0 = pts[i-1]
            d = math.hypot(xi - x0, yi - y0)
            dp[i] = min(dp[i], dp[i-1] + d / vw)

        # 2) Tunnel in from any earlier j
        #    Stop when the terrain dips below yi.
        for j in range(i-1, -1, -1):
            xj, yj   = pts[j]
            xj1, yj1 = pts[j+1]
            lo, hi = min(yj, yj1), max(yj, yj1)

            if lo <= yi <= hi:
                # Compute intersection I on segment j->(j+1) at height yi
                if yj1 != yj:
                    slope = (xj1 - xj) / (yj1 - yj)
                    xI = xj + slope*(yi - yj)
                else:
                    xI = xj1
                # Walk from (xj,yj) to I
                d1 = math.hypot(xI - xj, yi - yj)
                # Tunnel from I to (xi, yi)
                d2 = abs(xi - xI)
                dp[i] = min(dp[i], dp[j] + d1/vw + d2/vc)

            # Once yj <= yi, no further mountains cover yi from the left
            if yj <= yi:
                break

        # 3) Tunnel out to any future k
        for k in range(i+1, n):
            xk, yk   = pts[k]
            xkm, ykm = pts[k-1]
            lo, hi = min(ykm, yk), max(ykm, yk)

            if lo <= yi <= hi:
                # Intersection I at height yi on segment (k-1)->k
                if yk != ykm:
                    slope = (xk - xkm) / (yk - ykm)
                    xI = xkm + slope*(yi - ykm)
                else:
                    xI = xkm
                # Walk from I to (xk, yk)
                d1 = math.hypot(xk - xI, yk - yi)
                # Tunnel from (xi, yi) to I
                d2 = abs(xI - xi)
                dp[k] = min(dp[k], dp[i] + d1/vw + d2/vc)

            # Once yk <= yi, no further coverage
            if yk <= yi:
                break

    # Print minimum time to reach last point
    print(f"{dp[n-1]:.10f}")

if __name__ == "__main__":
    main()
```
