#include <bits/stdc++.h>
using namespace std;

struct Big {
    vector<uint32_t> limb;

    void trim() {
        while (!limb.empty() && limb.back() == 0) {
            limb.pop_back();
        }
    }

    void shl1_or(int bit) {
        uint64_t carry = bit;
        for (uint32_t &x : limb) {
            uint64_t cur = (uint64_t)x * 2 + carry;
            x = (uint32_t)cur;
            carry = cur >> 32;
        }
        if (carry) {
            limb.push_back((uint32_t)carry);
        }
    }

    void mul_small_add(uint32_t mul, uint32_t add) {
        uint64_t carry = add;
        for (uint32_t &x : limb) {
            uint64_t cur = (uint64_t)x * mul + carry;
            x = (uint32_t)cur;
            carry = cur >> 32;
        }
        if (carry) {
            limb.push_back((uint32_t)carry);
        }
    }

    uint32_t div_small(uint32_t div) {
        uint64_t rem = 0;
        for (int i = (int)limb.size() - 1; i >= 0; --i) {
            uint64_t cur = (rem << 32) | limb[i];
            limb[i] = (uint32_t)(cur / div);
            rem = cur % div;
        }
        trim();
        return (uint32_t)rem;
    }

    bool bit(int pos) const {
        int w = pos / 32;
        int b = pos % 32;
        return w < (int)limb.size() && ((limb[w] >> b) & 1u);
    }

    int bit_length() const {
        if (limb.empty()) {
            return 0;
        }
        uint32_t high = limb.back();
        return ((int)limb.size() - 1) * 32 + (32 - __builtin_clz(high));
    }
};

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

static int bits_per_message(int len) {
    Big capacity;
    capacity.limb.push_back(1);
    for (int i = 0; i < len; ++i) {
        capacity.mul_small_add(95, 0);
    }
    return capacity.bit_length() - 1;
}

static string encode_chunk(const vector<unsigned char> &bits, int from, int count, int len) {
    Big x;
    for (int i = 0; i < count; ++i) {
        x.shl1_or(bits[from + i]);
    }

    string body(len, ' ');
    for (int i = len - 1; i >= 0; --i) {
        int digit = (int)x.div_small(95);
        body[i] = char(32 + digit);
    }
    return body;
}

static vector<unsigned char> decode_chunk(const string &body, int count) {
    Big x;
    for (unsigned char ch : body) {
        if (ch < 32 || ch > 126) {
            continue;
        }
        x.mul_small_add(95, int(ch - 32));
    }

    vector<unsigned char> bits;
    bits.reserve(count);
    for (int i = count - 1; i >= 0; --i) {
        bits.push_back(x.bit(i) ? 1 : 0);
    }
    return bits;
}

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;
    }

    if (n == 1) {
        if (agent_id == 0) {
            cout << "! " << endl;
        } else {
            cout << "halt" << endl;
        }
        return 0;
    }

    if (max_msg_len <= 0) {
        cout << "halt" << endl;
        return 0;
    }

    const int total = n * n;
    vector<unsigned char> my_bits;
    my_bits.reserve(owned_count(total, num_agents, agent_id));

    auto query = [&](int r, int c) {
        cout << "? " << r << ' ' << c << endl;
        string reply;
        if (!(cin >> reply)) {
            exit(0);
        }
        return (unsigned char)(reply == "1");
    };

    for (int idx = agent_id; idx < total; idx += num_agents) {
        int r = idx / n + 1;
        int c = idx % n + 1;
        my_bits.push_back(query(r, c));
    }

    if (agent_id != 0) {
        int per_message = bits_per_message(max_msg_len);
        for (int pos = 0; pos < (int)my_bits.size(); pos += per_message) {
            int take = min(per_message, (int)my_bits.size() - pos);
            cout << "> 0 " << encode_chunk(my_bits, pos, take, max_msg_len) << endl;
            string reply;
            if (!(cin >> reply)) {
                return 0;
            }
        }
        cout << "halt" << endl;
        return 0;
    }

    vector<vector<unsigned char>> grid(n + 1, vector<unsigned char>(n + 1, 0));
    for (int idx = 0, p = 0; idx < total; idx += num_agents, ++p) {
        int r = idx / n + 1;
        int c = idx % n + 1;
        grid[r][c] = my_bits[p];
    }

    int per_message = bits_per_message(max_msg_len);
    vector<vector<string>> messages_by_agent(num_agents);
    vector<int> remaining_messages(num_agents, 0);
    int total_remaining = 0;
    for (int id = 1; id < num_agents; ++id) {
        int bit_count = owned_count(total, num_agents, id);
        remaining_messages[id] = (bit_count + per_message - 1) / per_message;
        total_remaining += remaining_messages[id];
        messages_by_agent[id].reserve(remaining_messages[id]);
    }

    string line;
    while (total_remaining > 0) {
        cout << "< ?" << endl;
        if (!getline(cin >> ws, line)) {
            return 0;
        }
        if (line == "- -") {
            continue;
        }
        size_t sep = line.find(' ');
        if (sep == string::npos) {
            continue;
        }
        string sender_token = line.substr(0, sep);
        string body = line.substr(sep + 1);
        int sender = stoi(sender_token);
        if (1 <= sender && sender < num_agents && remaining_messages[sender] > 0) {
            messages_by_agent[sender].push_back(body);
            --remaining_messages[sender];
            --total_remaining;
        }
    }

    for (int id = 1; id < num_agents; ++id) {
        int bit_count = owned_count(total, num_agents, id);
        vector<unsigned char> bits;
        bits.reserve(bit_count);
        for (const string &body : messages_by_agent[id]) {
            int take = min(per_message, bit_count - (int)bits.size());
            vector<unsigned char> chunk = decode_chunk(body, take);
            bits.insert(bits.end(), chunk.begin(), chunk.end());
        }
        for (int idx = id, p = 0; idx < total; idx += num_agents, ++p) {
            int r = idx / n + 1;
            int c = idx % n + 1;
            grid[r][c] = bits[p];
        }
    }

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

    vector<vector<int>> seen(n + 1, vector<int>(n + 1, 0));
    vector<vector<pair<int, int>>> parent(n + 1, vector<pair<int, int>>(n + 1, {-1, -1}));
    vector<vector<char>> parent_step(n + 1, vector<char>(n + 1, 0));
    queue<pair<int, int>> q;
    if (grid[1][1]) {
        seen[1][1] = 1;
        q.push({1, 1});
    }

    while (!q.empty() && !seen[n][n]) {
        auto [r, c] = q.front();
        q.pop();
        for (int d = 0; d < 4; ++d) {
            int nr = r + dr[d];
            int nc = c + dc[d];
            if (nr < 1 || nr > n || nc < 1 || nc > n || seen[nr][nc] || !grid[nr][nc]) {
                continue;
            }
            seen[nr][nc] = 1;
            parent[nr][nc] = {r, c};
            parent_step[nr][nc] = step[d];
            q.push({nr, nc});
        }
    }

    if (!seen[n][n]) {
        cout << "halt" << endl;
        return 0;
    }

    string path;
    for (int r = n, c = n; !(r == 1 && c == 1);) {
        char ch = parent_step[r][c];
        path.push_back(ch);
        auto [pr, pc] = parent[r][c];
        r = pr;
        c = pc;
    }
    reverse(path.begin(), path.end());

    cout << "! " << path << endl;
    return 0;
}
