#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <queue>
#include <string>
#include <vector>

using namespace std;

namespace {

struct Edge {
    int a, b;
    int r, c;
    char step;
};

void send_line(const string &s) {
    cout << s << '\n';
    cout.flush();
}

string read_line() {
    string s;
    if (!getline(cin, s)) exit(0);
    return s;
}

int assigned_count(int total, int agents, int id) {
    if (id >= total) return 0;
    return (total - 1 - id) / agents + 1;
}

string encode_bits(const vector<unsigned char> &bits, int start, int max_chars) {
    int remaining = static_cast<int>(bits.size()) - start;
    int pairs = min(max_chars / 2, (remaining + 12) / 13);
    string encoded;
    encoded.reserve(pairs * 2);

    for (int i = 0; i < pairs; ++i) {
        int val = 0;
        for (int b = 0; b < 13; ++b) {
            int pos = start + i * 13 + b;
            if (pos < static_cast<int>(bits.size()) && bits[pos]) val |= 1 << b;
        }
        encoded.push_back(static_cast<char>(32 + val % 95));
        encoded.push_back(static_cast<char>(32 + val / 95));
    }

    return encoded;
}

void send_message_to_zero(const string &body) {
    send_line("> 0 " + body);
    read_line();
}

int room_id(int cols, int rr, int cc) {
    return rr * cols + cc;
}

vector<Edge> build_edges(int n) {
    int rows = (n + 1) / 2;
    int cols = rows;
    vector<Edge> edges;
    edges.reserve(2 * rows * (cols - 1));

    for (int r = 0; r < rows; ++r) {
        for (int c = 0; c < cols; ++c) {
            int a = room_id(cols, r, c);
            if (c + 1 < cols) {
                int b = room_id(cols, r, c + 1);
                edges.push_back({a, b, 2 * r + 1, 2 * c + 2, 'R'});
            }
            if (r + 1 < rows) {
                int b = room_id(cols, r + 1, c);
                edges.push_back({a, b, 2 * r + 2, 2 * c + 1, 'D'});
            }
        }
    }

    return edges;
}

char invert_step(char ch) {
    if (ch == 'U') return 'D';
    if (ch == 'D') return 'U';
    if (ch == 'L') return 'R';
    return 'L';
}

string build_path_from_edges(int n, const vector<Edge> &edges,
                             const vector<unsigned char> &open_edge) {
    int rows = (n + 1) / 2;
    int cols = rows;
    int room_count = rows * cols;

    vector<vector<pair<int, char>>> g(room_count);
    for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
        if (!open_edge[i]) continue;
        const Edge &e = edges[i];
        g[e.a].push_back({e.b, e.step});
        g[e.b].push_back({e.a, invert_step(e.step)});
    }

    vector<int> parent(room_count, -1);
    vector<char> step(room_count, 0);
    queue<int> q;
    parent[0] = 0;
    q.push(0);

    while (!q.empty() && parent[room_count - 1] == -1) {
        int v = q.front();
        q.pop();

        for (auto [to, ch] : g[v]) {
            if (parent[to] != -1) continue;
            parent[to] = v;
            step[to] = ch;
            q.push(to);
        }
    }

    if (parent[room_count - 1] == -1) return "";

    string compressed;
    for (int v = room_count - 1; v != 0; v = parent[v]) {
        compressed.push_back(step[v]);
    }
    reverse(compressed.begin(), compressed.end());

    string path;
    path.reserve(compressed.size() * 2);
    for (char ch : compressed) {
        path.push_back(ch);
        path.push_back(ch);
    }
    return path;
}

string build_path_from_cells(int n, const vector<unsigned char> &open) {
    int total = n * n;
    vector<int> parent(total, -1);
    vector<char> step(total, 0);
    queue<int> q;

    parent[0] = 0;
    q.push(0);

    const int dr[4] = {-1, 1, 0, 0};
    const int dc[4] = {0, 0, -1, 1};
    const char dir[4] = {'U', 'D', 'L', 'R'};

    while (!q.empty() && parent[total - 1] == -1) {
        int v = q.front();
        q.pop();
        int r = v / n;
        int c = v % n;

        for (int k = 0; k < 4; ++k) {
            int nr = r + dr[k];
            int nc = c + dc[k];
            if (nr < 0 || nr >= n || nc < 0 || nc >= n) continue;

            int to = nr * n + nc;
            if (!open[to] || parent[to] != -1) continue;

            parent[to] = v;
            step[to] = dir[k];
            q.push(to);
        }
    }

    if (parent[total - 1] == -1) return "";

    string path;
    for (int v = total - 1; v != 0; v = parent[v]) {
        path.push_back(step[v]);
    }
    reverse(path.begin(), path.end());
    return path;
}

}  // namespace

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

    int N, NUM_AGENTS, AGENT_ID, MAX_MSG_LEN;
    if (!(cin >> N >> NUM_AGENTS >> AGENT_ID >> MAX_MSG_LEN)) return 0;
    string startup_rest;
    getline(cin, startup_rest);

    if (N == 1) {
        if (AGENT_ID == 0) send_line("!");
        else send_line("halt");
        return 0;
    }

    vector<Edge> edges = build_edges(N);
    int edge_count = static_cast<int>(edges.size());

    int my_count = assigned_count(edge_count, NUM_AGENTS, AGENT_ID);
    vector<unsigned char> local_bits;
    local_bits.reserve(my_count);

    for (int idx = AGENT_ID; idx < edge_count; idx += NUM_AGENTS) {
        send_line("? " + to_string(edges[idx].r) + " " + to_string(edges[idx].c));
        string reply = read_line();
        local_bits.push_back(!reply.empty() && reply[0] == '1');
    }

    if (AGENT_ID != 0) {
        int pos = 0;
        while (pos < my_count || pos == 0) {
            string header = "C" + to_string(pos) + ":";
            int room = MAX_MSG_LEN - static_cast<int>(header.size());
            if (room <= 0) {
                send_message_to_zero("F0:");
                send_line("halt");
                return 0;
            }

            int capacity_bits = (room / 2) * 13;
            bool is_final = pos + capacity_bits >= my_count;
            header[0] = is_final ? 'F' : 'C';
            string payload = encode_bits(local_bits, pos, room);
            send_message_to_zero(header + payload);
            pos += static_cast<int>(payload.size() / 2) * 13;
            if (is_final) break;
        }

        send_line("halt");
        return 0;
    }

    vector<unsigned char> open_edge(edge_count, 0);
    for (int i = 0; i < my_count; ++i) {
        int idx = i * NUM_AGENTS;
        open_edge[idx] = local_bits[i];
    }

    vector<unsigned char> finished(NUM_AGENTS, 0);
    finished[0] = 1;
    int done = 1;

    while (done < NUM_AGENTS) {
        send_line("< ?");
        string reply = read_line();
        if (reply == "- -") continue;

        size_t space = reply.find(' ');
        if (space == string::npos) continue;

        int sender = stoi(reply.substr(0, space));
        string body = reply.substr(space + 1);

        if (!body.empty() && body[0] == 'F') {
            if (!finished[sender]) {
                finished[sender] = 1;
                ++done;
            }
        }

        if (body.empty() || (body[0] != 'C' && body[0] != 'F')) continue;

        size_t colon = body.find(':');
        if (colon == string::npos) continue;

        int start = stoi(body.substr(1, colon - 1));
        string payload = body.substr(colon + 1);
        int sender_count = assigned_count(edge_count, NUM_AGENTS, sender);

        for (int i = 0; i + 1 < static_cast<int>(payload.size()); i += 2) {
            int lo = static_cast<unsigned char>(payload[i]) - 32;
            int hi = static_cast<unsigned char>(payload[i + 1]) - 32;
            if (lo < 0 || lo >= 95 || hi < 0 || hi >= 95) continue;

            int val = lo + hi * 95;
            for (int b = 0; b < 13; ++b) {
                int local_pos = start + (i / 2) * 13 + b;
                if (local_pos >= sender_count) break;

                int idx = sender + local_pos * NUM_AGENTS;
                if (idx < edge_count) open_edge[idx] = (val >> b) & 1;
            }
        }
    }

    string path = build_path_from_edges(N, edges, open_edge);
    if (path.empty()) {
        vector<unsigned char> open(N * N, 0);
        for (int idx = 0; idx < N * N; ++idx) {
            int r = idx / N + 1;
            int c = idx % N + 1;
            send_line("? " + to_string(r) + " " + to_string(c));
            string reply = read_line();
            open[idx] = !reply.empty() && reply[0] == '1';
        }
        path = build_path_from_cells(N, open);
    }
    send_line("! " + path);
    return 0;
}
