Loading

Codeforces Round #753 (Div. 3) F. Robot on the Board 2(记忆化搜索/好题)

The robot is located on a checkered rectangular board of size 𝑛×𝑚n×m (𝑛n rows, 𝑚m columns). The rows in the board are numbered from 11 to 𝑛n from top to bottom, and the columns — from 11 to 𝑚m from left to right.

The robot is able to move from the current cell to one of the four cells adjacent by side.

Each cell has one of the symbols 'L', 'R', 'D' or 'U' written on it, indicating the direction in which the robot will move when it gets in that cell — left, right, down or up, respectively.

The robot can start its movement in any cell. He then moves to the adjacent square in the direction indicated on the current square in one move.

  • If the robot moves beyond the edge of the board, it falls and breaks.
  • If the robot appears in the cell it already visited before, it breaks (it stops and doesn't move anymore).

Robot can choose any cell as the starting cell. Its goal is to make the maximum number of steps before it breaks or stops.

Determine from which square the robot should start its movement in order to execute as many commands as possible. A command is considered successfully completed if the robot has moved from the square on which that command was written (it does not matter whether to another square or beyond the edge of the board).

Input

The first line contains an integer 𝑡t (1≤𝑡≤100001≤t≤10000) — the number of test cases in the test.

Each test case's description is preceded by a blank line. Next is a line that contains integers 𝑛n and 𝑚m (1≤𝑛≤20001≤n≤2000; 1≤𝑚≤20001≤m≤2000) — the height and width of the board. This line followed by 𝑛n lines, the 𝑖i-th of which describes the 𝑖i-th line of the board. Each of them is exactly 𝑚m letters long and consists of symbols 'L', 'R', 'D' and 'U'.

It is guaranteed that the sum of sizes of all boards in the input does not exceed 4⋅1064⋅106.

Output

For each test case, output three integers 𝑟r, 𝑐c and 𝑑d (1≤𝑟≤𝑛1≤r≤n; 1≤𝑐≤𝑚1≤c≤m; 𝑑≥0d≥0), which denote that the robot should start moving from cell (𝑟,𝑐)(r,c) to make the maximum number of moves 𝑑d. If there are several answers, output any of them.

Example

input

Copy

7

1 1
R

1 3
RRL

2 2
DL
RU

2 2
UD
RU

3 2
DL
UL
RU

4 4
RRRD
RUUD
URUD
ULLR

4 4
DDLU
RDDU
UUUU
RDLD

output

Copy

1 1 1
1 1 3
1 1 4
2 1 3
3 1 5
4 3 12
1 1 4

题目大意是给定一个地图,地图上每个位置有一个字母表示这个位置可以走的方向。现在可以任意选一个位置放置机器人,问在哪放机器人能让它走的最远并求出最远距离。

这个题显然需要用到记忆话搜索。整体思路就是枚举每个位置,如果这个位置已经被搜过则更新答案,如果没有被搜过则从这里进行搜索看看能走多远。还有细节需要注意:走的若干条路径可能有环,而环上各个点的答案都是环的长度。详情见代码注释。

#include <iostream>
#include <stack>
#define fi first
#define se second
using namespace std;
char mp[2005][2005];
int dp[2005][2005], d[2005][2005], id[2005][2005];//dp[i][j]表示答案 d[i][j]表示对于这一次dfs,走到这个点的深度
//id[i][j]表示这一趟dfs的编号
int n, m;
void dfs(int x, int y, int dep, int _id) {
    int nx = x, ny = y;
    d[x][y] = dep;
    id[x][y] = _id;
    dp[x][y] = 0;
    if(mp[x][y] == 'U') {//下一个位置
        nx--;
    } else if(mp[x][y] == 'D') {
        nx++;
    } else if(mp[x][y] == 'L') {
        ny--;
    } else if(mp[x][y] == 'R') {
        ny++;
    }
    if(nx < 1 || nx > n || ny < 1 || ny > m) {//break了
        dp[x][y] = 1;//更新dp数组
    } else if(d[nx][ny]) {//环的话需要把环上所有都更新了
        if(id[nx][ny] == _id) {//如果遇到的是同一趟的经过的点 说明是环
            //遇到环了
            int len_cycle = dep - d[nx][ny] + 1;//环长
            int cx = nx, cy = ny;
            while(cx != x || cy != y) {//把整个环都遍历一边 更新
                dp[cx][cy] = len_cycle;
                if(mp[cx][cy] == 'U') {
                    cx--;
                } else if(mp[cx][cy] == 'D') {
                    cx++;
                } else if(mp[cx][cy] == 'L') {
                    cy--;
                } else if(mp[cx][cy] == 'R') {
                    cy++;
                }
            }
            dp[x][y] = len_cycle;
        } else {//遇到的是别的趟的dfs走过的点 直接更新答案(这时候必然不是环)
            dp[x][y] = dp[nx][ny] + 1;
        }
    } else {
        dfs(nx, ny, dep + 1, _id);
        if(!dp[x][y]) dp[x][y] = dp[nx][ny] + 1;//如果当前的dp值没有被环更新
        //注意一定要判断 因为如果一个位置已经在环中被更新了dp值,这里再更新就会比真正的值大1
    }
}
int main() {
    int t;
    cin >> t;
    while(t--) {
        cin >> n >> m;
        for(int i = 1; i <= n; i++) {
            scanf("%s", mp[i] + 1);
        }
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                dp[i][j] = -1;
                d[i][j] = id[i][j] = 0;
            }
        }
        int ans = 0, ansx = 0, ansy = 0;
        int cnt = 0;
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                if(dp[i][j] == -1) {
                    //进行搜索
                    dfs(i, j, 1, ++cnt);
                } 
                if(dp[i][j] > ans) {//更新答案
                    ans = dp[i][j];
                    ansx = i, ansy = j;
                }
            }
        }
        cout << ansx << " " << ansy << " " << ans << endl;
    }
    return 0;
}
posted @ 2021-11-05 21:33  脂环  阅读(78)  评论(0编辑  收藏  举报