• 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;
    }
    
  • 相关阅读:
    让原生select只读,即是有disabled的的感觉,但是却不实现disabled的功能
    log4j配置 简单jsp中调用查看报表配置 解析excel、txt为bean对象配置
    css背景渐变
    myeclipse始终build workspace
    spring实现重定向
    Mysql错误---
    POJ 1087 A Plug for UNIX 【最大流】
    POJ 3281 Dining 【最大流】【神建模】
    POJ 2135 Farm Tour 【模板】【最小费用最大流】
    LibreOJ 116 有源汇有上下界最大流 【模板】【上下界最大流】
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/15515326.html
Copyright © 2020-2023  润新知