1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <iostream>
#include <string>
#include <deque>
#include <iomanip>
#include <limits>

using namespace std;

struct Gap {
    int s, e;
    [[nodiscard]] int len() const {
        return e == -1 ? numeric_limits<int>::max() : e - s;
    }
};

int L, v0, v1, v2, v3;
deque<Gap> g1, g2, g3;

auto gaps(const string &line) {
    deque<Gap> gaps;
    int gs{}, ge;
    bool in_gap = false;
    for (int i = 0; i < size(line); ++i) {
        if (line[i] == '.' && !in_gap) {
            in_gap = true;
            gs = i;
        }
        if (line[i] == '#' && in_gap) {
            in_gap = false;
            ge = i;
            gaps.push_back({gs, ge});
        }
    }
    gaps.push_back({in_gap ? gs : (int)size(line), -1});
    return gaps;
}

double right_overtake_time(double pos, double time, double max_time, deque<Gap>::iterator &iter) {
    int final_pos = g2[1].s;
    double d_pos = time * v3;
    iter = g3.begin();
    while (iter->e != -1) {
        if (iter->e + d_pos > pos + 1) break;
        g3.pop_front();
        iter = g3.begin();
    }
    double exp_gap_len = final_pos - pos + 1 - v3 * (final_pos - pos) / v0;
    while (true) {
        double gs = max(pos, iter->s + d_pos);
        double rem_len = iter->len() - (gs - iter->s - d_pos);
        double end_time = time - (gs - pos) / v3 + (final_pos - pos) / v0;
        if (end_time > max_time) {
            return -1;
        } else if (exp_gap_len <= rem_len) {
            return end_time;
        } else if (iter->e != -1) {
            g3.pop_front();
            iter = g3.begin();
        } else {
            return -1;
        }
    }
}

double left_overtake_time(double pos, double time) {
    int final_pos = g2[1].s;
    double d_pos = time * v1;
    auto iter = g1.begin();
    while (iter->e != -1) {
        auto n = next(iter);
        if (n->s + d_pos > pos) break;
        iter = n;
        g1.pop_front();
    }
    if (iter->e == -1) {
        return time + (final_pos - pos) / v0;
    }
    double dtv0 = (final_pos + 1 - (iter->e + d_pos)) / v1;
    double dtv1 = (final_pos - pos) / v0;
    return time + max(dtv0, dtv1);
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> L >> v0 >> v1 >> v2 >> v3;
    v0 -= v2;
    v1 -= v2;
    v3 -= v2;
    v2 = 0;
    string l1, l2, l3;
    cin >> l1 >> l2 >> l3;
    l3[0] = '.';
    g1 = gaps(l1);
    g2 = gaps(l2);
    g3 = gaps(l3);
    double ct{}, pos{};
    while (size(g2) > 1) {
        ct += (g2.front().len() - 1.) / v0;
        pos = g2.front().e - 1;
        double dtl = left_overtake_time(pos, ct);
        auto r_curr_gap = g3.begin();
        double dtr = right_overtake_time(pos, ct,dtl, r_curr_gap);
        ct = dtr == -1 ? dtl : dtr;
        g2.pop_front();
        pos = g2.front().s;
    }
    double l1_curr_pos = g1.back().s + ct * v1;
    if (l1_curr_pos > pos) {
        double dt = (l1_curr_pos - pos) / (v0 - v1);
        pos += dt * v0;
        ct += dt;
    }
    double l3_curr_pos = g3.back().s + ct * v3;
    if (l3_curr_pos > pos) {
        double dt = (l3_curr_pos - pos) / (v0 - v3);
        ct += dt;
    }
    cout << fixed << setprecision(15) << ct << '\n';
}