Yet Another Walking Robot (map容器+重载)

题目连接: Yet Another Walking Robot

题目:

There is a robot on a coordinate plane. Initially, the robot is located at the point (0,0). Its path is described as a string s of length n consisting of characters ‘L’, ‘R’, ‘U’, ‘D’.

Each of these characters corresponds to some move:

‘L’ (left): means that the robot moves from the point (x,y) to the point (x−1,y);
‘R’ (right): means that the robot moves from the point (x,y) to the point (x+1,y);
‘U’ (up): means that the robot moves from the point (x,y) to the point (x,y+1);
‘D’ (down): means that the robot moves from the point (x,y) to the point (x,y−1).
The company that created this robot asked you to optimize the path of the robot somehow. To do this, you can remove any non-empty substring of the path. But this company doesn’t want their customers to notice the change in the robot behavior. It means that if before the optimization the robot ended its path at the point (xe,ye), then after optimization (i.e. removing some single substring from s) the robot also ends its path at the point (xe,ye).

This optimization is a low-budget project so you need to remove the shortest possible non-empty substring to optimize the robot’s path such that the endpoint of his path doesn’t change. It is possible that you can’t optimize the path. Also, it is possible that after the optimization the target path is an empty string (i.e. deleted substring is the whole string s).

Recall that the substring of s is such string that can be obtained from s by removing some amount of characters (possibly, zero) from the prefix and some amount of characters (possibly, zero) from the suffix. For example, the substrings of “LURLLR” are “LU”, “LR”, “LURLLR”, “URL”, but not “RR” and “UL”.

You have to answer t independent test cases.

Input
The first line of the input contains one integer t (1≤t≤1000) — the number of test cases.
The next 2t lines describe test cases. Each test case is given on two lines. The first line of the test case contains one integer n (1≤n≤2⋅105) — the length of the robot’s path. The second line of the test case contains one string s consisting of n characters ‘L’, ‘R’, ‘U’, ‘D’ — the robot’s path.
It is guaranteed that the sum of n over all test cases does not exceed 2⋅105 (∑n≤2⋅105).

Output
For each test case, print the answer on it. If you cannot remove such non-empty substring that the endpoint of the robot’s path doesn’t change, print -1. Otherwise, print two integers l and r such that 1≤l≤r≤n — endpoints of the substring you remove. The value r−l+1 should be minimum possible. If there are several answers, print any of them.

Example
Input

4
4
LRUD
4
LURD
5
RRUDU
5
LLDDR
Output
1 2
1 4
3 4
-1
大致题意:
机器人可以往上下左右四个方向跑, 问你有没有余缀操作, 如果有的话把最短的余缀操作除去(输出余缀片段的起始和结束下标)
注: 余缀操作指的是重复操作, 即: 若机器人往上走后再往下走, 这是没意义的, 因此是余缀操作.

解题思路:

其实看机器人是否存在余缀操作, 就看他是否重复走过某点(x,y)即可.
因此我们比较容易联想到用map<点坐标, 步数>去进行记录.
题中又要最短的余缀片段, 那我们只需要进行一下比较记录即可

AC代码:

#include 
#define ll long long
using namespace std;
struct node {
      //表示点坐标
	int x, y;
	bool operator < (const node &a) const {
      //重载 < 为了存储map容器的key值
		if (x != a.x) return x < a.x;
		return y < a.y;
	}
};
map<node, int> m; //点坐标, 步数
int main(void)
{
     
	int t; cin >> t;
	while (t--) {
     
		int n; scanf("%d", &n);
		string s; cin >> s; m.clear(); //多组输入, 记得清空map容器
		int res = 0x7fffffff, resbeg = -1, resend = -1; //默认余缀片段长度无限长, 开始和结束的位置都是-1
		
		int x = 0, y = 0; //初始位置
		m[{
     0, 0}] = 0; //经过0步数可以到达(0, 0)点

		for (int i = 0; i < n; i++) {
      //i从0开始的, 所以当前步数为 i+1
			if (s[i] == 'L') y--;
			else if (s[i] == 'R') y++;
			else if (s[i] == 'U') x--;
			else x++;

			/* 进行完第i+1次操作后我们到达的坐标位置判断 */
			if (m[{
     x, y}] || (x == y && x == 0)) {
      //如果我们到过(x, y) 那么除了(0, 0) 我们所花费的步数一定非0
				if (i + 1 - m[{
     x, y}] < res) {
      //如果当前片段比res记录的片段长度长, 则更新res和起始, 结束点位置.
					res = i + 1 - m[{
     x, y}]; 
					resbeg = m[{
     x, y}], resend = i + 1;
				}
				if (res == 2) break; //如果片段长度为2了, 是最短的片段, 可以直接结束.(解释见代码结束)
			}
			m[{
     x, y}] = i + 1; //要更新m[{x,y}]的值, 因为如果后续i=j时还有到达(x, y)点的操作, 那res值也会是当前i+1与其j+1的差值.
		}

		if (resbeg == -1) cout << "-1" << endl; //如果起始点的坐标没变化, 那一定是没有余缀片段.
		else printf("%d %d\n", resbeg + 1, resend); //见下文
	}
	return 0;
}

至于为什么有res == 2 这一剪枝, 是这样的, 如果你走到某个点, 又回到这个点, 那其操作一定要大于等于2次 因此2次为最小解, 即使最小解有多个, 根据题目output中的 **If there are several answers, print any of them.**这句话, 易知当前解为有效解.

至于输出时输出 resbeg+1和resend, 我们的i+1是进行完第i+1次操作后我们到达(x, y)点, 那么当操作次数为resbeg时, 我们刚好到达(x, y)点, 因此不能删除resbeg这次操作, 应从resbeg+1处开始删除. 同理, 进行完第resend操作后, 我们会回到(x, y)点, 因此第resend应该被删除. 所以删除的区间应该为[resbeg+1, resend].

其实这篇文章主要为了纪念一下自己学会了重载(太菜了), 以前都是跟学长学的pair+map, 总感觉写make_pair有点麻烦
我看网上也有大佬用的pair+map, 思路其实都是一样的, 如果想看代码的话也可以看看他们的, 我就不再展示了.

END

你可能感兴趣的:(STL容器题目,c++,acm竞赛,算法,stl,c语言)