#include template using pi = std::pair; template using vc = std::vector; template using pqg = std::priority_queue, std::greater>; struct CustomHash { static uint64_t splitmix64(uint64_t x) { x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); } }; using u32 = uint32_t; using i64 = int64_t; using pii = pi; #define for_(i, l, r, vars...) \ for (std::make_signed_t i = (l), i##end = (r), ##vars; \ i <= i##end; \ ++i) #define foreach_ref_(i, container) for (auto &i : (container)) #define read_container_(type, name, size) \ type name(size); \ foreach_ref_(i, name) std::cin >> i template constexpr auto chkmin(Tp &a, Tp b) -> bool { return b < a ? a = b, true : false; } template constexpr auto chkmax(Tp &a, Tp b) -> bool { return a < b ? a = b, true : false; } template constexpr auto ispow2(Tp i) -> bool { return i && (i & -i) == i; } #define TPL_SIZE_(Tuple) std::tuple_size_v> namespace tuple_detail_ { template constexpr auto subtuple_impl_(Tuple &&t, std::index_sequence) { return std::make_tuple(std::get(t)...); } template constexpr auto apply2_impl_(BinOp &&f, Tuple &&lhs, Tuple &&rhs, std::index_sequence) { return std::make_tuple( std::forward(f)(std::get(lhs), std::get(rhs))...); } } // namespace tuple_detail_ template constexpr auto subtuple(Tuple &&t) { static_assert(Begin <= TPL_SIZE_(Tuple) && Len <= TPL_SIZE_(Tuple) && Begin + Len <= TPL_SIZE_(Tuple), "Out of range"); return tuple_detail_::subtuple_impl_(t, std::make_index_sequence()); } template constexpr auto tuple_push(Tp &&v, Tuple &&t) { static_assert(TPL_SIZE_(Tuple) > 0, "Pop from empty tuple"); return std::tuple_cat(subtuple<0, Pos>(t), std::make_tuple(v), subtuple(t)); } template constexpr auto tuple_push_front(Tp &&v, Tuple &&t) { return tuple_push<0>(v, t); } template constexpr auto tuple_push_back(Tp &&v, Tuple &&t) { return tuple_push(v, t); } template constexpr auto tuple_pop(Tuple &&t) { static_assert(TPL_SIZE_(Tuple) > 0, "Pop from empty tuple"); return std::tuple_cat(subtuple<0, Pos>(t), subtuple(t)); } template constexpr auto tuple_pop_front(Tuple &&t) { return tuple_pop<0>(t); } template constexpr auto tuple_pop_back(Tuple &&t) { return tuple_pop(t); } template constexpr auto apply2(BinOp &&f, Tuple &&lhs, Tuple &&rhs) { return tuple_detail_::apply2_impl_( f, lhs, rhs, std::make_index_sequence()); } #define OO_PTEQ_(op) \ template \ constexpr auto operator op(std::pair lhs, \ const std::pair &rhs) { \ return {lhs.first op rhs.first, lhs.second op rhs.second}; \ } \ template \ constexpr auto operator op(std::tuple const &lhs, \ std::tuple const &rhs) { \ return apply2([](auto &&l, auto &&r) { return l op r; }, lhs, rhs); \ } \ template \ constexpr std::pair &operator op##=(std::pair &lhs, \ const std::pair &rhs) { \ lhs.first op## = rhs.first; \ lhs.second op## = rhs.second; \ return lhs; \ } \ template \ constexpr auto operator op##=(std::tuple &lhs, \ const std::tuple &rhs) { \ return lhs = lhs op rhs; \ } OO_PTEQ_(+) OO_PTEQ_(-) OO_PTEQ_(*) OO_PTEQ_(/) OO_PTEQ_(%) OO_PTEQ_(&) OO_PTEQ_(|) OO_PTEQ_(^) OO_PTEQ_(<<) OO_PTEQ_(>>) #undef OO_PTEQ_ #undef TPL_SIZE_ template std::istream &operator>>(std::istream &is, std::pair &p) { return is >> p.first >> p.second; } template std::ostream &operator<<(std::ostream &os, const std::pair &p) { return os << p.first << ' ' << p.second; } template std::istream &operator>>(std::istream &is, std::tuple &p) { std::apply([&](Ts &...targs) { ((is >> targs), ...); }, p); return is; } template std::ostream &operator<<(std::ostream &os, const std::tuple &p) { std::apply( [&](Ts const &...targs) { std::size_t n{0}; ((os << targs << (++n != sizeof...(Ts) ? " " : "")), ...); }, p); return os; } template ().begin()), typename Ct::iterator> && std::is_same_v().end()), typename Ct::iterator>> * = nullptr> std::basic_ostream &operator<<(std::basic_ostream &os, const Ct &x) { if (x.begin() == x.end()) return os; for (auto it = x.begin(); it != x.end() - 1; ++it) os << *it << ' '; os << x.back(); return os; } const u32 OFFSET = 5; const u32 N = 3e5 + OFFSET; const u32 M = 1.2e6 + OFFSET; const i64 INF64 = 0x3f3f3f3f3f3f3f3f; const pii DIR4[4] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; using namespace std; struct Edge { i64 w; int to, next; Edge(i64 _w = 0, int _to = 0, int _next = 0): w(_w), to(_to), next(_next) {} } e[M]; int head[N], cnt_edge; void addEdge(int x, int y, i64 w = 1) { e[++cnt_edge] = Edge(w, y, head[x]); head[x] = cnt_edge; } i64 dis[N]; void dijkstra(int s) { pqg> q; memset(dis, 0x3f, sizeof(dis)); q.emplace(dis[s] = 0, s); while (!q.empty()) { auto [dis_now, now] = q.top(); q.pop(); if (dis[now] < dis_now) continue; for (int i = head[now], to; i; i = e[i].next) if (dis[to = e[i].to] > dis[now] + e[i].w) q.emplace(dis[to] = dis[now] + e[i].w, to); } } auto solve([[maybe_unused]] int t_ = 0) -> void { int n, m; cin >> n >> m; i64 p, q; cin >> p >> q; read_container_(vc, maps, n); int s = n * m; auto encode = [&](int x, int y) -> int { return x * m + y; }; auto valid = [&](int x, int y) -> bool { return x >= 0 && x < n && y >= 0 && y < m && maps[x][y] != '#'; }; for_(i, 0, n - 1) for_(j, 0, m - 1) switch (maps[i][j]) { case '.': addEdge(s, encode(i, j), 0); break; case 'L': if (valid(i - 1, j + 1)) addEdge(encode(i - 1, j + 1), encode(i, j), p); if (valid(i + 1, j + 1)) addEdge(encode(i + 1, j + 1), encode(i, j), p); if (valid(i, j + 2)) addEdge(encode(i, j + 2), encode(i, j), q); break; case 'R': if (valid(i - 1, j - 1)) addEdge(encode(i - 1, j - 1), encode(i, j), p); if (valid(i + 1, j - 1)) addEdge(encode(i + 1, j - 1), encode(i, j), p); if (valid(i, j - 2)) addEdge(encode(i, j - 2), encode(i, j), q); break; case 'U': if (valid(i + 1, j - 1)) addEdge(encode(i + 1, j - 1), encode(i, j), p); if (valid(i + 1, j + 1)) addEdge(encode(i + 1, j + 1), encode(i, j), p); if (valid(i + 2, j)) addEdge(encode(i + 2, j), encode(i, j), q); break; case 'D': if (valid(i - 1, j - 1)) addEdge(encode(i - 1, j - 1), encode(i, j), p); if (valid(i - 1, j + 1)) addEdge(encode(i - 1, j + 1), encode(i, j), p); if (valid(i - 2, j)) addEdge(encode(i - 2, j), encode(i, j), q); break; default: break; } dijkstra(s); i64 ans = INT64_MAX; for_(i, 0, n - 1) for_(j, 0, m - 1) if (i64 d1 = dis[encode(i, j)]; d1 != INF64) for (auto &&[di, dj] : DIR4) if (auto ii = i + di, jj = j + dj; valid(ii, jj)) if (i64 d2 = dis[encode(ii, jj)]; d2 != INF64) chkmin(ans, d1 + d2); cout << (ans == INT64_MAX ? -1 : ans) << '\n'; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int i_ = 0; solve(i_); return 0; }