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

using namespace std;

struct DSU {
    vector<int> parent;
    vector<int> sz;

    void init(int n) {
        parent.resize(n);
        sz.assign(n, 1);
        iota(parent.begin(), parent.end(), 0);
    }

    int find(int x) {
        while (parent[x] != x) {
            parent[x] = parent[parent[x]];
            x = parent[x];
        }
        return x;
    }

    void unite(int a, int b) {
        a = find(a);
        b = find(b);
        if (a == b) return;
        if (sz[a] < sz[b]) swap(a, b);
        parent[b] = a;
        sz[a] += sz[b];
    }
};

int N;
int NUM_AGENTS;
int AGENT_ID;
int MAX_MSG_LEN;
int ROOMS;
vector<vector<int>> adj;
DSU dsu;

int room_id_from_cell(int r, int c) {
    return ((r - 1) / 2) * ROOMS + ((c - 1) / 2);
}

pair<int, int> passage_rooms(int r, int c) {
    if (r % 2 == 1) {
        return {room_id_from_cell(r, c - 1), room_id_from_cell(r, c + 1)};
    }
    return {room_id_from_cell(r - 1, c), room_id_from_cell(r + 1, c)};
}

void add_open_passage(int r, int c) {
    auto [u, v] = passage_rooms(r, c);
    adj[u].push_back(v);
    adj[v].push_back(u);
    dsu.unite(u, v);
}

void output_claim(const string& path) {
    if (path.empty()) {
        cout << "!\n";
    } else {
        cout << "! " << path << "\n";
    }
    cout.flush();
}

bool claim_if_connected() {
    int start = 0;
    int target = ROOMS * ROOMS - 1;
    if (dsu.find(start) != dsu.find(target)) return false;

    vector<int> parent(ROOMS * ROOMS, -1);
    queue<int> q;
    q.push(start);
    parent[start] = start;

    while (!q.empty()) {
        int u = q.front();
        q.pop();
        if (u == target) break;
        for (int v : adj[u]) {
            if (parent[v] == -1) {
                parent[v] = u;
                q.push(v);
            }
        }
    }

    if (parent[target] == -1) return false;

    string path;
    int cur = target;
    while (cur != start) {
        int p = parent[cur];
        int pr = p / ROOMS;
        int pc = p % ROOMS;
        int cr = cur / ROOMS;
        int cc = cur % ROOMS;

        if (cr == pr && cc == pc + 1) path += "RR";
        else if (cr == pr && cc == pc - 1) path += "LL";
        else if (cr == pr + 1 && cc == pc) path += "DD";
        else if (cr == pr - 1 && cc == pc) path += "UU";
        cur = p;
    }
    reverse(path.begin(), path.end());

    output_claim(path);
    return true;
}

string pack_bits(const vector<char>& bits, int l, int r) {
    string msg;
    msg.reserve((r - l + 5) / 6);
    for (int i = l; i < r; i += 6) {
        int value = 0;
        for (int b = 0; b < 6 && i + b < r; ++b) {
            if (bits[i + b]) value |= (1 << b);
        }
        msg.push_back(char(33 + value));
    }
    return msg;
}

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

    if (!(cin >> N >> NUM_AGENTS >> AGENT_ID >> MAX_MSG_LEN)) return 0;

    if (N == 1) {
        if (AGENT_ID == 0) {
            output_claim("");
        } else {
            cout << "halt\n";
            cout.flush();
        }
        return 0;
    }

    ROOMS = (N + 1) / 2;

    vector<pair<int, int>> all_passages;
    all_passages.reserve((N * N - 1) / 2);
    for (int r = 1; r <= N; ++r) {
        for (int c = 1; c <= N; ++c) {
            if ((r % 2 == 1) != (c % 2 == 1)) {
                all_passages.push_back({r, c});
            }
        }
    }

    sort(all_passages.begin(), all_passages.end(), [](const auto& a, const auto& b) {
        int da = abs(a.first - a.second);
        int db = abs(b.first - b.second);
        if (da != db) return da < db;
        int sa = a.first + a.second;
        int sb = b.first + b.second;
        if (sa != sb) return sa < sb;
        return a < b;
    });

    int K = (int)all_passages.size();
    int chunk_bits = min(240, max(6, MAX_MSG_LEN * 6));
    chunk_bits = max(6, (chunk_bits / 6) * 6);

    vector<int> target_counts(NUM_AGENTS, 0);
    long long agent0_weight = max(1, chunk_bits + 2 - NUM_AGENTS);
    long long total_weight = agent0_weight + 1LL * (NUM_AGENTS - 1) * chunk_bits;
    long long prefix = 0;
    for (int i = 0; i < NUM_AGENTS; ++i) {
        long long w = (i == 0) ? agent0_weight : chunk_bits;
        long long next = prefix + w;
        target_counts[i] = (int)(next * K / total_weight - prefix * K / total_weight);
        prefix = next;
    }

    vector<vector<pair<int, int>>> work(NUM_AGENTS);
    for (int i = 0; i < NUM_AGENTS; ++i) {
        work[i].reserve(target_counts[i]);
    }

    vector<int> used(NUM_AGENTS, 0);
    for (int p = 0; p < K; ++p) {
        int best_agent = 0;
        long long best_value = -1;
        for (int i = 0; i < NUM_AGENTS; ++i) {
            long long value = 1LL * (p + 1) * target_counts[i] - 1LL * used[i] * K;
            if (value > best_value) {
                best_value = value;
                best_agent = i;
            }
        }
        work[best_agent].push_back(all_passages[p]);
        used[best_agent]++;
    }

    if (AGENT_ID != 0) {
        vector<char> bits;
        bits.reserve(work[AGENT_ID].size());

        for (auto [r, c] : work[AGENT_ID]) {
            cout << "? " << r << ' ' << c << "\n";
            cout.flush();
            string ans;
            if (!(cin >> ans)) return 0;
            bits.push_back(ans == "1");

            if ((int)bits.size() % chunk_bits == 0) {
                string msg = pack_bits(bits, (int)bits.size() - chunk_bits, (int)bits.size());
                cout << "> 0 " << msg << "\n";
                cout.flush();
                string ok;
                if (!(cin >> ok)) return 0;
            }
        }

        int rem = (int)bits.size() % chunk_bits;
        if (rem > 0) {
            string msg = pack_bits(bits, (int)bits.size() - rem, (int)bits.size());
            cout << "> 0 " << msg << "\n";
            cout.flush();
            string ok;
            if (!(cin >> ok)) return 0;
        }

        cout << "halt\n";
        cout.flush();
        return 0;
    }

    adj.assign(ROOMS * ROOMS, {});
    dsu.init(ROOMS * ROOMS);

    vector<int> message_ready_turns;
    for (int agent = 1; agent < NUM_AGENTS; ++agent) {
        int count = target_counts[agent];
        int full = count / chunk_bits;
        for (int s = 1; s <= full; ++s) {
            message_ready_turns.push_back(s * chunk_bits + s + 1);
        }
        if (count % chunk_bits != 0) {
            message_ready_turns.push_back(count + full + 2);
        }
    }
    sort(message_ready_turns.begin(), message_ready_turns.end());

    vector<int> next_passage_idx(NUM_AGENTS, 0);
    int turn = 1;
    int messages_received = 0;
    int my_idx = 0;

    while (messages_received < (int)message_ready_turns.size() || my_idx < target_counts[0]) {
        if (messages_received < (int)message_ready_turns.size() && message_ready_turns[messages_received] <= turn) {
            cout << "< ?\n";
            cout.flush();
            string sender_str, body;
            if (!(cin >> sender_str >> body)) return 0;
            if (sender_str != "-") {
                int sender = stoi(sender_str);
                for (char ch : body) {
                    int value = ch - 33;
                    for (int b = 0; b < 6 && next_passage_idx[sender] < target_counts[sender]; ++b) {
                        if ((value >> b) & 1) {
                            auto [r, c] = work[sender][next_passage_idx[sender]];
                            add_open_passage(r, c);
                        }
                        next_passage_idx[sender]++;
                    }
                }
                messages_received++;
                if (claim_if_connected()) return 0;
            }
            turn++;
        } else if (my_idx < target_counts[0]) {
            auto [r, c] = work[0][my_idx];
            cout << "? " << r << ' ' << c << "\n";
            cout.flush();
            string ans;
            if (!(cin >> ans)) return 0;
            if (ans == "1") {
                add_open_passage(r, c);
                if (claim_if_connected()) return 0;
            }
            my_idx++;
            turn++;
        } else {
            cout << ".\n";
            cout.flush();
            string ok;
            if (!(cin >> ok)) return 0;
            turn++;
        }
    }

    claim_if_connected();
    return 0;
}
