Robot on the Board 2 (爆搜+记忆化)

Robot on the Board 2

[Link](Problem - F - Codeforces)

题意

给你一个地图,每个格子有一个字母 L , R , U , D L,R,U,D L,R,U,D,你只能向该字母方向走且不能出界,不能走到走过的格子,问你从哪个格子出发走的最远。

思路

​ 可以想到一个很暴力做法,从每个点出发 d f s dfs dfs一遍,找到最远的即可,复杂度太高会 T T T

​ 考虑优化,对于某次 d f s dfs dfs如果我们走到了以前走过的点,那么我们可以在上次走的时候把这个点的最优解记录下来,即记忆化一下,这样复杂度就是 O ( n ) O(n) O(n)了。

​ 考虑怎么记录答案:

  1. 走到以前记忆过的,直接倒推即可

  2. 走到这次走的时候走的,即成环了,那么环上所有点的答案都是环长,其它的再倒推

  3. 走出边界,直接倒推

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <set>
#include <queue>
#include <vector>
#include <map>
#include <bitset>
#include <unordered_map>
#include <cmath> 
#include <stack>
#include <iomanip>
#include <deque> 
#include <sstream>
#define x first
#define y second
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 2010, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8, pi = acos(-1), inf = 1e20;
#define tpyeinput int
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int n, m, k;
char g[N][N];
bool st[N][N];
int f[N][N], cnt;
PII a[N * N];
void dfs(int x, int y) {
	if (x < 1 || x > n || y < 1 || y > m) {
		for (int i = cnt; i; i --)
			f[a[i].x][a[i].y] = cnt - i + 1;
		return ;
	}

	if (st[x][y]) {
		if (!f[x][y]) {
			int tmp = cnt, val = 0;
			while ((a[tmp].x != x || a[tmp].y != y)) tmp --, val ++;
			val ++;
			while ((a[cnt].x != x || a[cnt].y != y)) f[a[cnt].x][a[cnt].y] = val, cnt --;
			while (cnt) f[a[cnt].x][a[cnt].y] = val, cnt --, val ++;			
		}
		else {
			int val = 1;
			while (cnt) f[a[cnt].x][a[cnt].y] = f[x][y] + val, cnt --, val ++;			
		}
		return ;
	}

	a[++ cnt] = {x, y};
	st[x][y] = true;

	if (g[x][y] == 'U') dfs(x - 1, y);
	if (g[x][y] == 'D') dfs(x + 1, y);
	if (g[x][y] == 'L') dfs(x, y - 1);
	if (g[x][y] == 'R') dfs(x, y + 1);
}
int main() {
	ios::sync_with_stdio(false), cin.tie(0);
	int T;
	cin >> T;
	while (T -- ) {
		cin >> n >> m;
		for (int i = 1; i <= n; i ++)
			for (int j = 1; j <= m; j ++)
				cin >> g[i][j];
		;
		for (int i = 1; i <= n; i ++)
			for (int j = 1; j <= m; j ++)
				st[i][j] = false, f[i][j] = 0;
		
		for (int i = 1; i <= n; i ++)
			for (int j = 1; j <= m; j ++)
				if (!st[i][j]) {
					cnt = 0;
					dfs(i, j);
				}
		
		int res = 0, sx, sy;
		for (int i = 1; i <= n; i ++)
			for (int j = 1; j <= m; j ++)
				if (f[i][j] > res) res = f[i][j], sx = i, sy = j;
		
		cout << sx << ' ' << sy << ' ' << res << endl;
	}
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值