1. 程式人生 > 其它 >cf1607 F. Robot on the Board 2(搜尋)

cf1607 F. Robot on the Board 2(搜尋)

https://codeforces.com/contest/1607/problem/F

題意:

在一個字元矩陣上走,U/D/L/R表示站在某個字元上時,下一步必須按指定的方向走。不能越界或者走到已經走過的點上。問選哪個點為起點能走的步數最多

思路:

應該算dfs,但是據說c++17遞迴會爆棧,得放棄遞迴或者用c++14

從每個點出發能走的路徑是唯一確定的。每一次選一個沒確定答案的點開始搜尋,開path陣列記錄這次搜尋經過的點。搜尋過程中,如果遇到已經確定答案的點或者到達邊界,就回溯更新path上的所有點的答案;若遇到這次搜尋曾走過的點,說明這次搜尋遇到了一個環,就回溯找環的起點,並把環上所有點的距離更新為環的長度

#include <iostream>
using namespace std;
const signed N = 2010;
char G[N][N];
int cnt[N][N], pathx[N * N], pathy[N * N];
int n, m;
void sou(int x, int y)
{
    int len = 0, done = 0;
    while(x >= 1 && x <= n && y >= 1 && y <= m)
    {
        if(cnt[x][y] == -1) //這條路上有環
        {
            int cirbegin = len;
            while(pathx[cirbegin] != x || pathy[cirbegin] != y)
                cirbegin--; //往回找環的起點
            for(int i = cirbegin; i <= len; i++) //更新環上所有點的答案
                cnt[pathx[i]][pathy[i]] = len - cirbegin + 1;
            done = len - cirbegin + 1;
            len = cirbegin - 1;
            break;
        }
        if(cnt[x][y]) //到達已經有答案的點
        {
            done = cnt[x][y];
            break;
        }

        pathx[++len] = x, pathy[len] = y;
        cnt[x][y] = -1; //標記這次搜尋中走過該點

        switch(G[x][y])
        {
            case 'L': y--; break;
            case 'R': y++; break;
            case 'D': x++; break;
            case 'U': x--; break;
        }
    }

    for(int i = 1; i <= len; i++) //回溯更新路徑上所有點的答案
        cnt[pathx[len+1-i]][pathy[len+1-i]] = i + done;
}

signed main()
{
    int T; cin >> T; while(T--)
    {
        cin >> n >> m;
        for(int i = 1; i <= n; i++) cin >> G[i] + 1;

        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                cnt[i][j] = 0;

        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                if(!cnt[i][j]) sou(i, j);

        int xx = 0, yy = 0;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                if(cnt[xx][yy] < cnt[i][j])
                    xx = i, yy = j;
        cout << xx << ' ' << yy << ' ' << cnt[xx][yy] << '\n';
    }

    return 0;
}