Problem:
Score : 300 points

Problem Statement

Dolphin resides in two-dimensional Cartesian plane, with the positive x-axis pointing right and the positive y-axis pointing up.

Currently, he is located at the point (sx,sy). In each second, he can move up, down, left or right by a distance of 1.

Here, both the x- and y-coordinates before and after each movement must be integers.

He will first visit the point (tx,ty) where sx < tx and sy < ty, then go back to the point (sx,sy), then visit the point (tx,ty) again, and lastly go back to the point (sx,sy).

Here, during the whole travel, he is not allowed to pass through the same point more than once, except the points (sx,sy) and (tx,ty).

Under this condition, find a shortest path for him.

Constraints

-1000 ≤ sx < tx ≤ 1000

-1000 ≤ sy < ty ≤ 1000

sx,sy,tx and ty are integers.

Input

The input is given from Standard Input in the following format:

sx sy tx ty

Output

Print a string S that represents a shortest path for Dolphin.

The i-th character in S should correspond to his i-th movement.

The directions of the movements should be indicated by the following characters:

U: Up

D: Down

L: Left

R: Right

If there exist multiple shortest paths under the condition, print any of them.

Sample Input 1

0 0 1 2

Sample Output 1

UURDDLLUUURRDRDDDLLU

One possible shortest path is:

Going from (sx,sy) to (tx,ty) for the first time: (0,0) → (0,1) → (0,2) → (1,2)

Going from (tx,ty) to (sx,sy) for the first time: (1,2) → (1,1) → (1,0) → (0,0)

Going from (sx,sy) to (tx,ty) for the second time: (0,0) → (-1,0) → (-1,1) → (-1,2) → (-1,3) → (0,3) → (1,3) → (1,2)

Going from (tx,ty) to (sx,sy) for the second time: (1,2) → (2,2) → (2,1) → (2,0) → (2,-1) → (1,-1) → (0,-1) → (0,0)

Sample Input 2

-2 -2 1 1

Sample Output 2

UURRURRDDDLLDLLULUUURRURRDDDLLDL

Solution in Rust (1.15.1) (judge verdict: Accepted)

#[allow(unused_imports)]
use std::char::from_digit;
#[allow(unused_imports)]
use std::cmp::{max, min};
#[allow(unused_imports)]
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
#[allow(unused_imports)]
use std::fs::File;
#[allow(unused_imports)]
use std::io::prelude::*;
#[allow(unused_imports)]
use std::io::{stdin, stdout, BufReader, BufWriter, Stdin, Stdout, Write};
#[allow(unused_imports)]
use std::mem::swap;
#[allow(unused_imports)]
use std::str::FromStr;
 
type BoxResult<T> = Result<T, Box<std::error::Error>>;

const MAX: i64 = 1000;
const LIM: i64 = MAX + 1;
const RANGE: i64 = 2 * LIM + 1;
 
fn main() {
    let mut scanner = Scanner::new(stdin());
    let line = scanner.read_vector::<i64>().unwrap();
    let (sx, sy, tx, ty) = (line[0], line[1], line[2], line[3]);
    let mut used = vec![vec![false; RANGE as usize]; RANGE as usize];
    let mut path = vec![];
    for i in 0..4 {
        let mut p = if i % 2 == 0 {
            bfs(sx, sy, tx, ty, &mut used)
        } else {
            bfs(tx, ty, sx, sy, &mut used)
        };
        path.append(&mut p);
    }
    println!("{}", path.into_iter().collect::<String>());
}

fn bfs(sx: i64, sy: i64, tx: i64, ty: i64, used: &mut Vec<Vec<bool>>) -> Vec<char> {
    let mut visited = vec![vec![false; RANGE as usize]; RANGE as usize];
    let mut archive = vec![];
    let mut queue = VecDeque::new();
    let directions = vec![(-1, 0), (1, 0), (0, -1), (0, 1)];
    queue.push_front((sx, sy, 0, 0));
    visited[encode(sx)][encode(sy)] = true;
    while queue.len() > 0 {
        let (x, y, ox, oy) = queue.pop_back().unwrap();
        archive.push((x, y, ox, oy));
        if x == tx && y == ty {
            break;
        }
        for &(dx, dy) in directions.iter() {
            let new_x = x + dx;
            let new_y = y + dy;
            if !is_valid(new_x) || !is_valid(new_y) {
                continue;
            }
            let index_x = encode(new_x);
            let index_y = encode(new_y);
            if used[index_x][index_y] || visited[index_x][index_y] {
                continue;
            }
            queue.push_front((new_x, new_y, x, y));
            visited[index_x][index_y] = true;
        }
    }
    let mut path = vec![];
    let mut crt = archive.pop().unwrap();
    loop {
        let prv = archive.pop().unwrap();
        if crt.2 == prv.0 && crt.3 == prv.1 {
            if crt.0 > prv.0 {
                path.push('R');
            } else if crt.0 < prv.0 {
                path.push('L');
            } else if crt.1 > prv.1 {
                path.push('U');
            } else {
                path.push('D');
            }
            crt = prv;
            if crt.0 == sx && crt.1 == sy {
                break;
            }
            used[encode(crt.0)][encode(crt.1)] = true;
        }
    }
    path
}

fn encode(v: i64) -> usize {
    (v + MAX + 1) as usize
}

fn is_valid(v: i64) -> bool {
    v >= -MAX - 1 && v <= MAX + 1
}

#[allow(dead_code)]
struct Scanner<R> {
    reader: BufReader<R>,
    buffer: String,
}
impl<R> Scanner<R>
where
    R: Read,
{
    #[allow(dead_code)]
    fn new(inner: R) -> Scanner<R> {
        let reader = BufReader::new(inner);
        let buffer = String::new();
        Scanner {
            reader: reader,
            buffer: buffer,
        }
    }
    #[allow(dead_code)]
    fn with_capacity(capacity: usize, inner: R) -> Scanner<R> {
        let reader = BufReader::with_capacity(capacity, inner);
        let buffer = String::new();
        Scanner {
            reader: reader,
            buffer: buffer,
        }
    }
    #[allow(dead_code)]
    fn read_line(&mut self) -> BoxResult<String> {
        self.reader.read_line(&mut self.buffer)?;
        let cloned = self.buffer.trim().to_string();
        self.buffer.clear();
        Ok(cloned)
    }
    #[allow(dead_code)]
    fn read<T>(&mut self) -> BoxResult<T>
    where
        T: FromStr,
        T::Err: std::fmt::Debug,
        T::Err: std::error::Error,
        T::Err: 'static,
    {
        self.reader.read_line(&mut self.buffer)?;
        let parsed = self.buffer.trim().parse()?;
        self.buffer.clear();
        Ok(parsed)
    }
    #[allow(dead_code)]
    fn read_two<T, U>(&mut self) -> BoxResult<(T, U)>
    where
        T: FromStr,
        T: Copy,
        T::Err: std::fmt::Debug,
        T::Err: std::error::Error,
        T::Err: 'static,
        U: FromStr,
        U: Copy,
        U::Err: std::fmt::Debug,
        U::Err: std::error::Error,
        U::Err: 'static,
    {
        self.reader.read_line(&mut self.buffer)?;
        let (a, b) = {
            let params = self.buffer.trim().split_whitespace().collect::<Vec<_>>();
            let a = params[0].parse()?;
            let b = params[1].parse()?;
            (a, b)
        };
        self.buffer.clear();
        Ok((a, b))
    }
    #[allow(dead_code)]
    fn read_three<T>(&mut self) -> BoxResult<(T, T, T)>
    where
        T: FromStr,
        T: Copy,
        T::Err: std::fmt::Debug,
        T::Err: std::error::Error,
        T::Err: 'static,
    {
        let nums = self.read_vector()?;
        Ok((nums[0], nums[1], nums[2]))
    }
    #[allow(dead_code)]
    fn read_vector<T>(&mut self) -> BoxResult<Vec<T>>
    where
        T: FromStr,
        T::Err: std::fmt::Debug,
        T::Err: std::error::Error,
        T::Err: 'static,
    {
        self.reader.read_line(&mut self.buffer)?;
        let parsed_vec = self
            .buffer
            .trim()
            .split_whitespace()
            .map(|s| s.parse())
            .collect::<Result<Vec<_>, _>>()?;
        self.buffer.clear();
        Ok(parsed_vec)
    }
    #[allow(dead_code)]
    fn read_matrix<T>(&mut self, lines: usize) -> BoxResult<Vec<Vec<T>>>
    where
        T: FromStr,
        T::Err: std::fmt::Debug,
        T::Err: std::error::Error,
        T::Err: 'static,
    {
        let mut parsed_matrix = vec![];
        for _ in 0..lines {
            self.reader.read_line(&mut self.buffer)?;
            parsed_matrix.push(
                self.buffer
                    .trim()
                    .split_whitespace()
                    .map(|s| s.parse())
                    .collect::<Result<Vec<_>, _>>()?,
            );
            self.buffer.clear();
        }
        Ok(parsed_matrix)
    }
    #[allow(dead_code)]
    fn read_chars(&mut self) -> BoxResult<Vec<char>> {
        self.reader.read_line(&mut self.buffer)?;
        let chars = self.buffer.trim().chars().collect::<Vec<_>>();
        self.buffer.clear();
        Ok(chars)
    }
}