在一行上输入一个长度
,由大写字母、数字和分号(
)构成的字符串
,代表输入的指令序列。保证字符串中至少存在一个
,且末尾一定为
。
在一行上输出一个两个整数,代表小人最终位置的横纵坐标,使用逗号间隔。
A10;S20;W10;D30;X;A1A;B10A11;;A10;
10,-10
对于这个样例,我们模拟小人的移动过程:
第一个指令
是合法的,向左移动
个单位,到达
点;
第二个指令
是合法的,向下移动
个单位,到达
点;
第三个指令
是合法的,向上移动
个单位,到达
点;
第四个指令
是合法的,向右移动
个单位,到达
点;
第五个指令
不合法,跳过;
第六个指令
不合法,跳过;
第七个指令
不合法,跳过;
第八个指令
不合法,跳过;
第九个指令
是合法的,向左移动
个单位,到达
点。
ABC;AKL;DA1;D001;W023;A100;S00;
0,0
在这个样例中,全部指令均不合法,因此小人不移动。
A00;S01;W2;
0,1
本题已于下方时间节点更新,请注意题解时效性:
1. 2025-05-15 更新题面,新增几组hack数据(暂未进行重测)。
2. 2024-12-16 更新题面。
#include <iostream>
using namespace std;
bool law(string op) {
if(op[0] != 'A' && op[0] != 'S' && op[0] != 'W' && op[0] != 'D') return false;
op = op.substr(1);
for(int i = 0; i < op.size(); i++) {
if(op[i] >= '0' && op[i] <= '9') continue;
return false;
}
return true;
}
int move(string op) {
int num = 0, ind = 1;
while(op[ind]) {
num = num * 10 + op[ind] - '0';
ind++;
}
return num;
}
int main() {
string str;
while(cin >> str) {
int x = 0, y = 0, flag = 1;
while(flag) {
int ind = str.find(';');
if(ind == str.size() - 1) flag = 0;
string op = str.substr(0, ind);
str = str.substr(ind + 1);
if(!law(op)) continue;
int m = move(op);
switch(op[0]) {
case 'A':
x -= m;
break;
case 'W':
y += m;
break;
case 'S':
y -= m;
break;
case 'D':
x += m;
break;
}
}
cout << x << "," << y << endl;
}
return 0;
}
import re
def jug (text):
global ll
if text == '':
return 0
if text[-1].isdigit() and 1 < len(text) <= 3:
pattern = re.compile(r'[asdwASDW]\d{1,2}')
is_match = re.match(pattern, text)
if is_match:
ll.append(text.upper())
texts = input().split(';')
ll = []
x, y = 0, 0
for i in texts:
jug(i)
for _ in ll:
tmp = _[0]
if tmp == 'A':
x -= int(_[1:])
elif tmp == 'D':
x += int(_[1:])
elif tmp == 'S':
y -= int(_[1:])
else:
y += int(_[1:])
print(f'{x},{y}') #include<iostream>
#include<string>
#include<vector>
using namespace std;
bool check(string& s){ //检测子串是不是合法的
if(s.size()>3 || s.size() < 2) return false;
bool flag1=false,flag2=false;
if(s[0] == 'A' || s[0] == 'W' || s[0] == 'S' || s[0] == 'D'){
flag1=true;
} //是一位数字还是两位数字
if((s.size() == 2 && s[1] >= '0' && s[1] <= '9') || (s.size() == 3 && s[1] >= '0' && s[1] <= '9'
&& s[2] >= '0' && s[2] <= '9')){
flag2=true;
}
return flag1 && flag2;
}
pair<int,int>addNum(string& s){ //获取子串中的坐标
int n=s.size();
char c=s[0];
int num=stoi(s.substr(1)); //截取子串1号位到结尾的数字大小
pair<int,int>ans={0,0};
switch (c)
{
case 'A':ans.first=-num;break;
case 'D':ans.first=num;break;
case 'W':ans.second=num;break;
case 'S':ans.second=-num;break;
}
return ans;
}
void Solution(string &str,int& x,int& y){
int n=str.size();
int l=0,r=0;
while(r<n){
while(str[r] != ';'){
r++;
}
string s=str.substr(l,r-l); //双指针截除去';'的子串
if(check(s)){
x+=addNum(s).first;
y+=addNum(s).second;
}
l=r+1; //跳过';',取下一位位置;
r=l;
}
}
int main(){
string str;
cin>>str;
int x=0,y=0;
Solution(str, x, y);
cout<<x<<','<<y<<endl;
return 0;
}
import java.util.*;
/**
* @Title: Move
* @auth: J
* @date: 2022/5/24 13:17
* @Description:
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String all = sc.next();
String[] steps = all.split(";");
List<String> directions = new ArrayList<>();
directions.add("W");
directions.add("A");
directions.add("S");
directions.add("D");
Integer x = 0;
Integer y = 0;
// 过滤掉非法数据
for (String step : steps) {
if (step.length() < 2 || step.length() > 3) {
continue;
}
String direction = step.substring(0, 1); // 方向
try {
Integer len = Integer.parseInt(step.substring(1)); // 步长
if (!directions.contains(direction) || len < 0) {
continue;
}
switch (direction) {
case "W":
y += len;
break;
case "S":
y -= len;
break;
case "D":
x += len;
break;
case "A":
x -= len;
break;
}
} catch (NumberFormatException e) { // 如果步长非法,跳过
continue;
}
}
System.out.println(x + "," + y);
}
}
import re
lst = input().split(';')
x,y = 0,0
for s in lst:
if 2 <= len(s) <= 3:
# 判断是否为有效的字符串
a,b = s[0],s[1:]
if re.fullmatch(r'[A-Z]',a) and (re.fullmatch(r'\d{2}', b)&nbs***bsp;re.fullmatch(r'\d{1}', b)):
b = int(b)
if a == 'A':
x -= b
elif a == 'S':
y -= b
elif a == 'W':
y += b
elif a == 'D':
x += b
print('%d,%d'%(x,y)) #include <bits/stdc++.h>
using namespace std;
int main() {
string n;
while(cin>>n)
{string t;pair<int,int> p (0,0);
stringstream ss(n);
while(getline(ss,t,';'))
{
if(regex_match(t,regex("^A[0-9]*"))) p.first-=stoi(t.substr(1));
else if(regex_match(t,regex("^D[0-9]*"))) p.first+=stoi(t.substr(1));
else if(regex_match(t,regex("^W[0-9]*"))) p.second+=stoi(t.substr(1));
else if(regex_match(t,regex("^S[0-9]*"))) p.second-=stoi(t.substr(1));
else continue;
}
cout<<p.first<<","<<p.second<<endl;
}
return 0;
} #include <iostream>
#include <vector>
int main() {
int x = 0, y = 0;
char tmp;
//0 normal, -1 waste, 1 wait for num1, 2 wait for num2&nbs***bsp;end, 3 wait for end
int state = 0;
int direction = -1, bias = 0;
std::vector<std::vector<int>> aim = { {0, 1}, {-1, 0}, {0, -1}, {1, 0} };
while (std::cin.get(tmp))
{
if (tmp == '\n')
{
break;
}
switch (state)
{
case -1:
switch (tmp)
{
case ';' :
state = 0;
break;
default :
break;
}
break;
case 0 :
bias = 0;
switch (tmp)
{
case ';' :
state = 0;
break;
case 'W' :
direction = 0;
state = 1;
break;
case 'A':
direction = 1;
state = 1;
break;
case 'S':
direction = 2;
state = 1;
break;
case 'D':
direction = 3;
state = 1;
break;
default :
state = -1;
break;
}
break;
case 1:
switch (tmp)
{
case ';':
state = 0;
break;
default:
if (tmp <= '9' && tmp >= '0')
{
bias = bias * 10 + tmp - '0';
state = 2;
}
else
{
state = -1;
}
break;
}
break;
case 2:
switch (tmp)
{
case ';':
x += aim[direction][0] * bias;
y += aim[direction][1] * bias;
state = 0;
break;
default:
if (tmp <= '9' && tmp >= '0')
{
bias = bias * 10 + tmp - '0';
state = 3;
}
else
{
state = -1;
}
break;
}
break;
case 3:
switch (tmp)
{
case ';':
x += aim[direction][0] * bias;
y += aim[direction][1] * bias;
state = 0;
break;
default:
state = -1;
break;
}
break;
}
}
std::cout << x << ',' << y;
return 0;
} 状态机之状态转移大法。
#include<stdio.h>
#include<string>
#include<iostream>
using namespace std;
int main(){
string strs;
int x = 0;
int y = 0;
getline(cin,strs);
for(int i =0; i< strs.length();i++){
if(strs[i] == ';'){ //如果读取到;分隔符
int j =i-1;
int len = 0;
int step = 0;
while(strs[j]!=';' && j>=0) {//计算这一段的位移是两位数还是三位数
j--;
len++;
}
if(len==3) step =(strs[i-2]-48)*10+(strs[i-1]-48); //三位
else if(len==2) step =strs[i-1]-48; //两位
//判断输入是否合法
if((strs[i-1] >='0'&&strs[i-1] <='9')&&(strs[i-len] >='A'&&strs[i-len] <='Z')){
//判断方向
if(strs[i-len] == 'A') x = x-step;
else if (strs[i-len] == 'D') x = x+step;
else if (strs[i-len] == 'S') y = y-step;
else if (strs[i-len] == 'W') y = y+step;
}
}
}
cout<<x<<','<<y<<endl;
} // 2021-12-16
// cpp 选手
#include <iostream>
#include <string>
#include <sstream>
#include <set>
using namespace std;
set<char> gValidOP{'A', 'D', 'W', 'S'};
struct Point{
int x;
int y;
Point(int xx = 0, int yy = 0):x(xx), y(yy){}
Point(const Point& other)
{
this->x = other.x;
this->y = other.y;
}
Point& operator=(const Point& other)
{
this->x = other.x;
this->y = other.y;
return *this;
}
};
class CPosCalculator
{
public:
CPosCalculator(Point po = Point(0, 0)) : m_pos(po), m_op(0)
{
}
int ParseValidOp(const string& strOp)
{
// -1: 无效; 0: 无影响; 1: 有效,需要处理;
int iRet = 0;
bool bFirstValid = false;
bool bSecondValid = true;
if(!strOp.size()) return iRet;
for(int i = 0; i < strOp.size(); ++i)
{
if(i==0)
{
// 第一个字符是否为有效操作
if(gValidOP.count(strOp[i]))
{
bFirstValid = true;
if(strOp[i]=='A')
{
m_op = -1;
}
else if(strOp[i]=='D')
{
m_op = 1;
}
else if(strOp[i]=='W')
{
m_op = 2;
}
else
{
m_op = -2;
}
}
else
{
iRet = -1;
bSecondValid = false;
break;
}
}
else if(bFirstValid)
{
bSecondValid &= isdigit(strOp[i]);
}
}
if(bSecondValid)
{
iRet = 1;
m_offset = atoi(strOp.substr(1).c_str());
}
else
iRet = -1;
return iRet;
}
void Move()
{
switch(m_op)
{
case -1:
m_pos.x -= m_offset;
break;
case 1:
m_pos.x += m_offset;
break;
case -2:
m_pos.y -= m_offset;
break;
case 2:
m_pos.y += m_offset;
break;
}
}
Point& GetPos()
{
return m_pos;
}
private:
Point m_pos;
int m_op;
int m_offset;
};
int main()
{
string strIn;
while(getline(cin, strIn))
{
string strEle;
CPosCalculator calc;
int idx_off = 0;
int idx = -1;
do
{
idx = strIn.find_first_of(';', idx_off);
strEle = strIn.substr(idx_off, idx - idx_off);
int op = 0;
if((op = calc.ParseValidOp(strEle)) == 1)
{
calc.Move();
}
idx_off += (idx-idx_off + 1);
}while(idx != -1);
Point& pp = calc.GetPos();
cout << pp.x << "," << pp.y << endl;
}
return 0;
} import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String str = sc.nextLine();
int[] point = new int[2];
move(point, str);
System.out.println(point[0] + "," + point[1]);
}
}
// 坐标移动
public static void move(int[] point, String str) {
String[] arr = str.split(";");
for (String s : arr) {
if (isOk(s)) {
char direction = s.charAt(0);
int size = Integer.parseInt(s.substring(1));
switch (direction) {
case 'A':
point[0] -= size;
break;
case 'S':
point[1] -= size;
break;
case 'D':
point[0] += size;
break;
case 'W':
point[1] += size;
}
}
}
}
// 判断是否合法
public static boolean isOk(String str) {
if (str.length() < 2 || str.length() > 3) {
return false;
}
char temp;
for (int i=0; i<str.length(); i++) {
temp = str.charAt(i);
if (i == 0) {
if (temp != 'A' && temp != 'S' && temp != 'D' && temp != 'W') {
return false;
}
continue;
}
if (temp < '0' || temp > '9') {
return false;
}
}
return true;
}
} #include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct{
int x;
int y;
}tCoord;
void calculate(char *str, tCoord *coord)
{
int len = strlen(str);
if(len<2)
return;
for(int i=1; i<len; i++)
{
if(str[i]<'0' || str[i]>'9')
return;
}
switch(str[0])
{
case 'A':
coord->x -= atoi(&str[1]);
break;
case 'D':
coord->x += atoi(&str[1]);
break;
case 'W':
coord->y += atoi(&str[1]);
break;
case 'S':
coord->y -= atoi(&str[1]);
break;
default:
break;
}
}
int main() {
char str[10000]={0};
char *p;
char *delim = ";";
tCoord coord;
coord.x = 0;
coord.y = 0;
scanf("%s", str);
p = strtok(str, delim);
while (p)
{
calculate(p, &coord);
p = strtok(NULL, delim);
}
printf("%d,%d\n", coord.x, coord.y);
return 0;
} #include<stdio.h>
#include<string.h>
int main(){
char str[20000]={0};
int x=0,y=0,num;
gets(str);
int l=strlen(str);
for(int i=0;i<l;i++){
if(str[i]==';'&&(str[i-4]==';'||str[i-4]==NULL)){
if(str[i-2]>='0'&&str[i-2]<='9'&&str[i-1]>='0'&&str[i-1]<='9'){
num = (str[i-2]-48)*10+str[i-1]-48;
if(str[i-3]=='A')
x-=num;
else if(str[i-3]=='D')
x+=num;
else if(str[i-3]=='W')
y+=num;
else if(str[i-3]=='S')
y-=num;
}
}
if(str[i]==';'&&(str[i-3]==';'||str[i-3]==NULL)){
if(str[i-1]>='0'&&str[i-1]<='9'){
num = str[i-1]-48;
if(str[i-2]=='A')
x-=num;
else if(str[i-2]=='D')
x+=num;
else if(str[i-2]=='W')
y+=num;
else if(str[i-2]=='S')
y-=num;
}
}
}
printf("%d,%d",x,y);
} #include <bits/stdc++.h>
using namespace std;
int main(){
/*
下面是一个简单的例子 如:A10;S20;W10;D30;X;A1A;B10A11;;A10;
输入描述:一行字符串
输出描述:最终坐标,以逗号分隔
*/
//分别定义横纵坐标,读取字符串,若读到分号,对临时字符串进行解析
//长度小于2或大于3的直接抛弃;第一个字母非...,直接抛弃;除第一个字母外,其余位置存在字母的,直接抛弃;
//A:横坐标减操作;D:横坐标加操作;W:纵坐标加操作;S:纵坐标减操作
string inputStr;
while(cin >> inputStr){
int m = 0 , n = 0;
string tempStr;
for(int i = 0; i < inputStr.size(); i++){
if(inputStr[i] == ';'){
int len = tempStr.size();
if(len < 2 || len > 3) tempStr = "";
if(tempStr[0] != 'A' && tempStr[0] != 'D' && tempStr[0] != 'W' && tempStr[0] != 'S') tempStr = "";
int sum = 0;
for(int i = 1; i < tempStr.size(); i++){//临时字符串不为空,才会进来
if(tempStr[i] >= '0' && tempStr[i] <= '9') sum += (tempStr[i] - '0') * pow(10,(tempStr.size() - i - 1));
else{
tempStr = "";
break;
}
}
if(tempStr[0] == 'A') m -= sum;
if(tempStr[0] == 'D') m += sum;
if(tempStr[0] == 'W') n += sum;
if(tempStr[0] == 'S') n -= sum;
tempStr = "";
}
else{
tempStr += inputStr[i];
}
}
cout << m << "," << n << endl;
}
return 0;
} while True:
try:
s = input()
s = list(s.split(";"))
x,y = 0,0
for c in s:
if not c:
continue
elif c[0]=='A' and c[1:].isdigit():
x-=int(c[1:])
elif c[0]=='S' and c[1:].isdigit():
y-=int(c[1:])
elif c[0]=='W' and c[1:].isdigit():
y+=int(c[1:])
elif c[0]=='D' and c[1:].isdigit():
x+=int(c[1:])
print(str(x)+','+str(y))
except:
break import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = 0, y = 0;
while (sc.hasNext()) {
String[] strings = sc.nextLine().split(";");
for (String str : strings) {
if (2 <= str.length() && 3 >= str.length()) {
try {
int dist = Integer.parseInt(str.substring(1));
switch (str.charAt(0)) {
case 'A':
x -= dist;
break;
case 'S':
y -= dist;
break;
case 'W':
y += dist;
break;
case 'D':
x += dist;
break;
}
} catch (NumberFormatException ignored) {
}
}
}
System.out.println(x + "," + y);
}
}
} x,y=0,0
a=input().split(';')
for i in a:
try:
int(i[1:])
except:
continue
else:
if i[0]=='A':
x=x-int(i[1:])
if i[0]=='D':
x=x+int(i[1:])
if i[0]=='W':
y=y+int(i[1:])
if i[0]=='S':
y=y-int(i[1:])
print(str(x)+','+str(y)) 感觉题目没说清楚,就是那个空格出现的位置,好多玩家似乎都没考虑,比如 A 20; 这种,又或者是 A2 0 ; 空格可能出现的位置题目并没有明确说明,只是在例子中提到,但是好多玩家的解法里似乎都没考虑各种花式的空格插入的可能性,但似乎都过了(是我漏掉什么了吗)。
然后是非法字符,我最开始没看到数字长度最多为2,我以为是任意的整数,导致我的做法考虑得稍微多了点。
这个题 O(N) 的时间足矣,我的做法便是使用字符自动机从左开头扫描到结尾即可完成对这个字符串的分析,便类似一个在线算法,不用先分割,也不需要额外的数组去保存某个子串,向前指针走到到哪便分析到哪。
直接上C语言(含注释):
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h> // 在C中使用bool类型
char buffer[2000]; // 全局缓冲区
int sign; // 决定方向的正负,取+1/-1
int* pxy; // 指向要修改的 x 或者 y (根据按键的方向修改)
char* start; // 开始指针,指向单词的开头
char* forward; // 向前指针,指向单词的结尾
char* cur; // 当前游标位置
bool terminate; // 自动机是否终止
// 自动机启动
void startup()
{
// 指向 buffer 开头的前一个位置
start = forward = cur = buffer - 1;
pxy = NULL;
terminate = false;
}
// 负责获取下一个单词,以及决定自动机是否该停止
void next_word()
{
++forward;
while (*forward == ' ') ++forward; // 跳过下个单词开头的空格
start = forward;
while (*forward != ';') {
if (*forward == '\0') {
terminate = true;
return;
}
++forward;
}
}
// 字符自动机
void automaton(int* x, int* y)
{
startup();
// 每次循环处理一个单词
next_word();
while (!terminate) {
// 如果开头字符不是方向,说明有误,故跳过这个单词
switch (*start) {
case 'A':
sign = -1;
pxy = x;
break;
case 'D':
sign = 1;
pxy = x;
break;
case 'W':
sign = 1;
pxy = y;
break;
case 'S':
sign = -1;
pxy = y;
break;
default:
next_word();
continue;
}
cur = start + 1;
while (*cur == ' ') ++cur; // 跳过空格
if (!isdigit(*cur)) { // 如果方向后跟的不是数字则有误
next_word();
continue;
}
int number = *cur - '0';
while (isdigit(*++cur))
number = number * 10 + (*cur - '0');
while (*cur == ' ') ++cur; // 跳过空格
if (*cur != ';') { // 如果数字后跟的不是分号则有误
next_word();
continue;
}
*pxy += sign * number;
next_word();
}
}
int main()
{
int x, y;
while (scanf("%s", buffer) == 1) {
x = y = 0;
automaton(&x, &y);
printf("%d,%d\n", x, y);
}
return 0;
}
a = input()
a = a.split(';')
b = [0, 0]
for item in a:
if 2 <=len(item) <= 3:
if item[0] in ['A', 'S', 'W', 'D'] and item[1:].isdigit():
if item[0] == 'A':
b[0] -= int(item[1:])
elif item[0] == 'W':
b[-1] += int(item[1:])
elif item[0] == 'S':
b[-1] -= int(item[1:])
elif item[0] == 'D':
b[0] += int(item[1:])
print('{},{}'.format(b[0],b[-1])) #include <iostream>
using namespace std;
#define LINE_IS_END 0
#define CMD_UNVALID -1
#define CMD_VALID 1
/* Read a cmd in one line from cin
@command: store the cmd string
@return: status->{LINE_IS_END, CMD_UNVALID, CMD_VALID}
*/
int readCmd(string& command)
{
char tmp;
int cmd_size;
char direction;
command.clear();
while (cin.get(tmp))
{
switch (tmp) {
case '\n':
return LINE_IS_END;
case ';':
goto check;
default:
command.push_back(tmp);
//ignore error input which is too long due to the miss of semicolon
}
}
check:
cmd_size = command.size();
if (cmd_size < 2 || cmd_size >3) {
return CMD_UNVALID;
}
direction = command.front();
if (direction != 'A' && direction != 'D' &&
direction != 'W' && direction != 'S') {
return CMD_UNVALID;
}
tmp = command.at(1);
if (tmp < '0' || tmp > '9') {
return CMD_UNVALID;
}
if (cmd_size == 3) {
tmp = command.at(2);
if (tmp < '0' || tmp > '9') {
return CMD_UNVALID;
}
}
return CMD_VALID;
}
typedef struct position {
int x;
int y;
}pos_t;
//Assume the command is valid, if not so, no operation is done.
void move_pos(pos_t& pos, string& command)
{
char direction = command.front();
int dis = 0;
int cmd_size = command.size();
if (cmd_size < 2 || cmd_size >3) {
return;
}
dis = command.at(1) - '0';
if (cmd_size == 3){
dis = dis * 10 + command.at(2) - '0';
}
switch (direction) {
case 'A':
pos.x = pos.x - dis;
break;
case 'D':
pos.x = pos.x + dis;
break;
case 'W':
pos.y = pos.y + dis;
break;
case 'S':
pos.y = pos.y - dis;
break;
}
}
int main(void)
{
string cmd;
int ret;
pos_t pos = {0, 0};
while (true) {
ret = readCmd(cmd);
if (ret == CMD_VALID) {
move_pos(pos, cmd);
}
if (ret == LINE_IS_END) {
cout<<pos.x<<','<<pos.y;
break;
}
}
return 0;
}