2021中国大学生程序设计竞赛(CCPC)- 网络选拔赛 1009 Command Sequence

4 篇文章 0 订阅
3 篇文章 0 订阅

1009 Command Sequence

Problem Description

There is a robot that can move by receiving a sequence of commands.

There are four types of command in the command sequence:

U: robot moves one unit up.

D: robot moves one unit down.

L: robot moves one unit left.

R: robot moves one unit right.

Now, given a command sequence of length n. You need to find out how many substrings of the command sequence satisfy that if the robot execute the substring command, it can return to the starting position.

A substring is a contiguous sequence of characters within a string. For instance, “the best of” is a substring of “It was the best of times”. For example, “Itwastimes” is a subsequence of “It was the best of times”, but not a substring.

Input

This problem contains multiple test cases.

The first line contains an integer t (1≤t≤20) indicating the number of test cases.

For each test case, the first line contains one integer n (2≤n≤10^5).

The second line contains a UDLR string of length n.

Output

For each test case, output one line one integer indicating the answer.

Sample Input

1
6
URLLDR

Sample Output

2

题目大意:

一个机器人可以执行上下左右(UDLR)四个命令,执行每个命令时移动一个单位距离。

给定一条由UDLR组成的命令字符串,问有多少个子串满足当机器人执行完这个子串命令后可以回到起点。

例如UUDDUDLRRR的子串UD可以满足要求。

题解:

如果采用暴力的方法枚举每一个子串,那么一定会超时。

我们遍历整条命令,并记录执行完每一个命令的位置(x, y)。
如果有一个子串可以使机器人回到原点,那么执行子串前和执行子串后的位置(x, y)应该是相同的。

所以当我们执行完某个命令后,只需要判断当前位置(x, y)在之前有没有出现过,即可判断终点为当前位置的满足要求的子串数量。
例如如果当前位置(x, y)在之前出现过2次,说明有2个终点为当前位置的子串满足要求。

枚举所有终点不断累加当前(x, y)在之前出现过的次数即可得到答案。

我们可以用map<pair<int, int>, int>来记录每一个坐标出现的次数,到一个位置就记录当前位置map[{x, y}] ++,并不断累加前位置(x, y)在前面出现的次数res += map[{x, y}]。

注意起点(0, 0)不要忘了记录。

AC代码:

#include <iostream>
#include <map>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PAIR;
int main() {
    ios::sync_with_stdio(false);
    ll t;
    cin >> t;
    while (t --) {
        map<PAIR, ll> mp;
        mp[{0, 0}] ++; // 起点(0, 0)也要记录 
        ll n;
		string s;
        cin >> n >> s;
        ll res = 0, x = 0, y = 0; // 初始化坐标为(0, 0) 
        for (ll i = 0; i < s.length(); i ++) { // 遍历整条命令 
            if (s[i] == 'U') x ++; 
            else if (s[i] == 'D') x --;
            else if (s[i] == 'L') y ++;
            else if (s[i] == 'R') y --;
            res += mp[{x, y}]; // 累加当前位置(x, y)在前面出现的次数 
            mp[{x, y}] ++; // 记录当前位置 
        }
        cout << res << '\n';
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值