NowCode:HJ17 坐标移动

题目: 坐标移动

描述

我们定义一个无限大的二维网格上有一个小人,小人初始位置为 (0,0)(0,0) 点,小人可以读取指令上下左右移动。

一个合法的指令由三至四个符号组成:
∙ ∙第一个符号为 “A/D/W/S””A/D/W/S” 中的一个,代表小人移动的方向;分别代表向左、向右、向上、向下移动;记某个时刻小人的坐标为 (x,y)(x,y) ,向左移动一格即抵达 (x−1,y)(x−1,y) 、向右移动一格即抵达 (x+1,y)(x+1,y) 、向上移动一格即抵达 (x,y+1)(x,y+1) 、向下移动一格即抵达 (x,y−1)(x,y−1) 。
∙ ∙最后一个符号为 “;””;” ,代表指令的结束,该符号固定存在;
∙ ∙中间为一个 1-991-99 的数字,代表小人移动的距离。
如果你遇到了一个不合法的指令,则直接忽略;例如,指令 “A100;””A100;” 是不合法的,因为 100100 超出了 1-991-99 的范围;”Y10;””Y10;” 也是不合法的,因为 YY 不是 “A/D/W/S””A/D/W/S” 中的一个。

输出小人最终的坐标。

输入描述:

在一行上输入一个长度 1≦length(s)≦1041≦length(s)≦104 ,仅由可见字符构成的字符串 ss ,代表输入的指令序列。

输出描述:

在一行上输出一个两个整数,代表小人最终位置的横纵坐标,使用逗号间隔。

示例1

输入:

1
A10;S20;W10;D30;X;A1A;B10A11;;A10;

输出:

1
10,-10

说明:

1
2
3
4
5
6
7
8
9
10
对于这个样例,我们模拟小人的移动过程:
∙ ∙第一个指令 "A10;""A10;" 是合法的,向左移动 1010 个单位,到达 (−10,0)(−10,0) 点;
∙ ∙第二个指令 "S20;""S20;" 是合法的,向下移动 2020 个单位,到达 (−10,−20)(−10,−20) 点;
∙ ∙第三个指令 "W10;""W10;" 是合法的,向上移动 1010 个单位,到达 (−10,−10)(−10,−10) 点;
∙ ∙第四个指令 "D30;""D30;" 是合法的,向右移动 3030 个单位,到达 (20,−10)(20,−10) 点;
∙ ∙第五个指令 "X;""X;" 不合法,跳过;
∙ ∙第六个指令 "A1A;""A1A;" 不合法,跳过;
∙ ∙第七个指令 "B10A11;""B10A11;" 不合法,跳过;
∙ ∙第八个指令 ";"";" 不合法,跳过;
∙ ∙第九个指令 "A10;""A10;" 是合法的,向左移动 1010 个单位,到达 (10,−10)(10,−10) 点。

示例2

输入:

1
ABC;AKL;DA1;

输出:

1
0,0

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <cctype>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
using namespace std;

int main() {
std::string s;
getline(cin, s);
int start = 0;
int length = 0;
std::vector<std::string> instructions;
for (size_t i = 0; i < s.size(); ++i) {
if (s[i] == ';') {
length = i - start;
std::string ins = s.substr(start, length);
if (!ins.empty()) {
instructions.emplace_back(ins);
}
start = i + 1;
}
}
int x = 0;
int y = 0;
for (size_t i = 0; i < instructions.size(); ++i) {
if (instructions[i].size() != 2 && instructions[i].size() != 3) {
continue;
}
char ch = instructions[i][0];
if (ch != 'A' && ch != 'D' && ch != 'S' && ch != 'W') {
continue;
}
std::string numStr = instructions[i].substr(1);
bool isNumber = true;
for (char ch : numStr) {
if (!isdigit(ch)) {
isNumber = false;
break;
}
}

if (!isNumber || numStr.empty()) {
continue;
}
int distance = stoi(numStr);
if (distance < 1 || distance > 99) {
continue;
}
switch (ch) {
case 'A':
x -= distance;
break;
case 'D':
x += distance;
break;
case 'W':
y += distance;
break;
case 'S':
y -= distance;
break;
default:
break;
}
}
cout << x << "," << y << endl;

}
// 64 位输出请用 printf("%lld")#include <iostream>
using namespace std;

int main() {
int num = 0;
cin >> num;
int count = 0;
for (int i = 0; i <= 31; i++) {
count += (num >> i) & 1;
}
cout << count;
}
// 64 位输出请用 printf("%lld")

思路

  1. 输入处理:使用 getline 读取整行输入字符串。
  2. 指令分割:遍历字符串,每次遇到分号时,截取从上一个分号到当前分号的子字符串作为指令。
  3. 合法性验证
    • 长度检查:指令长度必须为2或3。
    • 方向检查:首字符必须是 ADWS
    • 数字检查:中间部分必须为1-99的整数。

此题挺好

HJ31 单词倒排 这道题与本题解法类似,都是将分割的的字符串存到vector容器里,再统一处理