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;
}