#include <bits/stdc++.h>
#include <chrono>
#include <ctime>
using namespace std;
using chrono::steady_clock;
using chrono::milliseconds;

#define sp " "
#define INF 1e18
#define INT_INF 1e9
typedef long long ll;
typedef pair<int,int> P;

chrono::steady_clock::time_point now_t;
chrono::steady_clock::time_point start_t;

random_device x;
mt19937 mt(x());

struct coord { int x; int y; };

const int N = 50;
vector<vector<int>> t(50,vector<int>(50));
vector<vector<int>> p(50,vector<int>(50));
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};
char direct[] = {'D','R','U','L'};

struct state {
    //状態を管理
    int l;
    vector<coord> route;
    vector<char> direct;//D,R,U,L 
    vector<int> score;
    vector<int> reach;//0 false 1 true
};


int get_rnd(int mod){
    return mt()%mod;
}

bool TIME_CHECK( int Limit ){
    now_t = steady_clock::now();
    if(chrono::duration_cast<milliseconds>(now_t-start_t) < milliseconds(Limit))return true;
    return false;
}

void enter(state &S){
    //入力
    int sx,sy;
  	cin >> sx >> sy;
  	coord s = {sx,sy};
  	S.route.push_back(s);
    for(int i = 0;i < 2500;i++)S.reach.push_back(0);
  	for(int i = 0;i < 50;i++){
        for(int j = 0;j < 50;j++){
            cin >> t[i][j];
        } 
    }
    for(int i = 0;i < 50;i++){
        for(int j = 0;j < 50;j++){
            cin >> p[i][j];
        }
    }
    S.reach[t[S.route[0].x][S.route[0].y]] = 1;
  	S.score.push_back(p[S.route[0].x][S.route[0].y]);
    S.l = 1;
    return;
}

void output(state S){
    //出力
    int l = S.l;
    for(int i = 0;i < l-1;++i){
        //cout << i << sp << S.route[i+1].x-S.route[0].x << sp << S.route[i+1].y-S.route[0].y << endl; 
        // if(S.route[i+1].x - S.route[i].x == 1)cout << "D";
        // if(S.route[i+1].x - S.route[i].x == -1)cout << "U";
        // if(S.route[i+1].y - S.route[i].y == 1)cout << "R";
        // if(S.route[i+1].y - S.route[i].y == -1)cout << "L";
        // //cout << endl;
        cout << S.direct[i];
    }
}

void dfs(state &S){
    state best_s = S;
    stack<state> st;
    st.push(S);
    while(!st.empty() && st.size() < 1000 && TIME_CHECK(1800)){
      state s = st.top();
      st.pop();
      int cx,cy,l;
      l = s.l;
      cx = s.route[l-1].x;
      cy = s.route[l-1].y;
      for(int i = 0;i < 4;i++){
        state T = s;
        if(cx+dx[i] < 0 || cx+dx[i] >= 50 || cy+dy[i] < 0 || cy+dy[i] >= 50)continue;
        else if(T.reach[t[cx+dx[i]][cy+dy[i]]] == 0){
          coord c = {cx+dx[i],cy+dy[i]};
          T.route.push_back(c);
          T.score.push_back(T.score[l-1] + p[c.x][c.y]);
          if(T.score[l] > best_s.score[best_s.l-1])best_s = T;
          if(st.size() > 50){
            if(T.score[l] < best_s.score[min(l,best_s.l - 1)]*9/10)continue;
          }
          T.reach[t[c.x][c.y]] = 1;
          T.direct.push_back(direct[i]);
          T.l += 1;
          st.push(T);
        }
      }
    }
    S = best_s;
}


//void mountain( state &S){
    //山登り
    // int l = S.l;
    // int n = get_rnd(l);
//}

// void AS ( state &S){
//     //焼きなまし
// }



/*
近傍の取り方でスコア悪化の確立が高すぎるもの、
変化がおおきすぎるものを選ぶとスコア改善しないので、
適切な近傍の取り方を考える
思いつかないなら山登りでよい
極力連続でなだらかな関数にする
近傍の取り方は2種類用意したほうがいい（できれば）
焼きなましの温度は対数的に減らす->確率は線形になる
線形的に減らす->確率は指数的になる

rand()は遅いので使わない
*/
int main(){
    start_t = steady_clock::now();
    state S;
    enter(S);
    // while(true){
    //     int res = greed(S);
    //     if(res == 0)continue;
    //     else break;
    // }
    dfs(S);
    output(S);
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cassert>
#include <cmath>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <cstdlib>

using namespace std;

#define mp make_pair
#define pb push_back
#define fi first
#define fs first
#define se second
#define li long long
#define lint long long
#define pii pair<int, int>
#define vi vector<int>

#define forn(i, n) for (int i = 0; i < (int)n; i++)
#define fore(i, b, e) for (int i = (int)b; i <= (int)e; i++)

using Vertex = pii;

struct Move {
	int fi, se, dir;
};

using Moves = vector<Move>;

const int QUERIES = 1000;
const int STARTW = 5000;
const int N = 30;
const int INF = 2e9;
const int dx[4] = {-1, +1, 0, 0};
const int dy[4] = {0, 0, -1, +1};
const int opp[4] = {1, 0, 3, 2};
const char symbol[4] = {'U', 'D', 'L', 'R'};

int edge[N][N][4];

bool valid(Vertex v) {
	return v.fi >= 0 && v.fi < N && v.se >= 0 && v.se < N;
}

Vertex apply(Vertex v, int move) {
	return {v.fi + dx[move], v.se + dy[move]};
}

pair<Moves, int> find_path(Vertex s, Vertex f) {
	vector<vi> dist(N, vi(N, INF));
	vector<vi> last_move(N, vi(N));

	set<pair<int, Vertex>> order;
	order.insert({0, s});
	dist[s.fi][s.se] = 0;
	while (!order.empty()) {
		auto cur = *order.begin();
		order.erase(order.begin());
		Vertex v = cur.se;
		// cerr << v.fi << " " << v.se << endl;
		if (v == f) {
			break;
		}
		if (dist[v.fi][v.se] != cur.fi) {
			continue;
		}
		forn(move, 4) {
			Vertex u = apply(v, move);
			if (valid(u)) {
				int new_dist = cur.fi + edge[v.fi][v.se][move];
				if (new_dist < dist[u.fi][u.se]) {
					dist[u.fi][u.se] = new_dist;
					last_move[u.fi][u.se] = move;
					order.insert({new_dist, u});
				}
			}
		}
	}
	vector<Move> moves;
	Vertex cur = f;
	while (cur != s) {
		Vertex prev = apply(cur, opp[last_move[cur.fi][cur.se]]);
		moves.pb({prev.fi, prev.se, last_move[cur.fi][cur.se]});
		cur = prev;
	}
	reverse(moves.begin(), moves.end());
	return {moves, dist[f.fi][f.se]};
}

string moves_to_string(const Moves& moves) {
	vector<char> s;
	for (Move move : moves) {
		s.pb(symbol[move.dir]);
	}
	return string(s.begin(), s.end());
}

void upd(Move move, int prediction) {
	// cerr << move.fi << " " << move.se << " " << move.dir << " " << prediction << endl;
	int new_val = (edge[move.fi][move.se][move.dir] == STARTW ? prediction : (edge[move.fi][move.se][move.dir] + prediction) / 2);
	edge[move.fi][move.se][move.dir] = new_val;
}

Move opp_move(Move move) {
	Vertex dest = apply({move.fi, move.se}, move.dir);
	return {dest.fi, dest.se, opp[move.dir]};
}

int main() {
	int avg = STARTW;
	forn(i, N)
		forn(j, N)
			forn(dir, 4) {
				edge[i][j][dir] = avg;
			}
	forn(q, QUERIES) {
		Vertex s, f;
		cin >> s.fi >> s.se >> f.fi >> f.se;
		auto result = find_path(s, f);
		// cerr << result.se << endl;
		Moves& moves = result.fi;
		string path = moves_to_string(moves);

		cout << path << endl;
		fflush(stdout);
		int correct_length;
		cin >> correct_length;

		for (Move move: moves) {
			double ratio = (double)edge[move.fi][move.se][move.dir] / result.se;
			//double ratio = 1. / moves.size();
			double prediction = ratio * correct_length;
			upd(move, prediction);
			upd(opp_move(move), prediction);
		}
		// recalc_avg();
	}
}
