首页 > 试题广场 >

坐标移动

[编程题]坐标移动
  • 热度指数:601202 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
\hspace{15pt}我们定义一个无限大的二维网格上有一个小人,小人初始位置为 (0,0) 点,小人可以读取指令上下左右移动。

\hspace{15pt}一个合法的指令由三至四个符号组成:
\hspace{23pt}\bullet\,第一个符号为 \texttt{ 中的一个,代表小人移动的方向;分别代表向左、向右、向上、向下移动;记某个时刻小人的坐标为 (x,y) ,向左移动一格即抵达 (x-1,y) 、向右移动一格即抵达 (x+1,y) 、向上移动一格即抵达 (x,y+1) 、向下移动一格即抵达 (x,y-1)
\hspace{23pt}\bullet\,最后一个符号为 \texttt{ ,代表指令的结束,该符号固定存在;
\hspace{23pt}\bullet\,中间为一个 \texttt{1-99} 的数字,代表小人移动的距离。
\hspace{15pt}如果你遇到了一个不合法的指令,则直接忽略;例如,指令 \texttt{ 是不合法的,因为 \texttt{100} 超出了 \texttt{1-99} 的范围;\texttt{ 也是不合法的,因为 \texttt{Y} 不是 \texttt{ 中的一个。

\hspace{15pt}输出小人最终的坐标。

输入描述:
\hspace{15pt}在一行上输入一个长度 1 \leqq {\rm length}(s) \leqq 10^4 ,仅由可见字符构成的字符串 s ,代表输入的指令序列。


输出描述:
\hspace{15pt}在一行上输出一个两个整数,代表小人最终位置的横纵坐标,使用逗号间隔。
示例1

输入

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

输出

10,-10

说明

\hspace{15pt}对于这个样例,我们模拟小人的移动过程:
\hspace{23pt}\bullet\,第一个指令 \texttt{ 是合法的,向左移动 10 个单位,到达 (-10,0) 点;
\hspace{23pt}\bullet\,第二个指令 \texttt{ 是合法的,向下移动 20 个单位,到达 (-10,-20) 点;
\hspace{23pt}\bullet\,第三个指令 \texttt{ 是合法的,向上移动 10 个单位,到达 (-10,-10) 点;
\hspace{23pt}\bullet\,第四个指令 \texttt{ 是合法的,向右移动 30 个单位,到达 (20,-10) 点;
\hspace{23pt}\bullet\,第五个指令 \texttt{ 不合法,跳过;
\hspace{23pt}\bullet\,第六个指令 \texttt{ 不合法,跳过;
\hspace{23pt}\bullet\,第七个指令 \texttt{ 不合法,跳过;
\hspace{23pt}\bullet\,第八个指令 \texttt{ 不合法,跳过;
\hspace{23pt}\bullet\,第九个指令 \texttt{ 是合法的,向左移动 10 个单位,到达 (10,-10) 点。
示例2

输入

ABC;AKL;DA1;

输出

0,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}')


发表于 2022-06-04 16:47:41 回复(1)
#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;
}

发表于 2022-05-29 15:15:47 回复(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);
    }
}

发表于 2022-05-24 13:29:27 回复(0)
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))


发表于 2022-05-21 00:10:33 回复(0)
这里可以用stream流解决解决;分号断续输入,然后再用正则表达式解决子字符串匹配问题。(代码很短,但是时间很长)
#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;
}


发表于 2022-04-12 20:19:19 回复(1)
#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;
}
状态机之状态转移大法。
发表于 2022-04-12 11:16:00 回复(0)
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        String str = in.nextLine();
        String[] strs = str.split(";");
        int x=0;
        int y=0;
        for(String s:strs){
            if(s.startsWith("A") && s.substring(1).matches("[0-9]{1,2}")){
               x =  x - Integer.parseInt(s.substring(1));
            }else if(s.startsWith("D") && s.substring(1).matches("[0-9]{1,2}")){
               x =  x + Integer.parseInt(s.substring(1));
            }else if(s.startsWith("S") && s.substring(1).matches("[0-9]{1,2}")){
               y =  y - Integer.parseInt(s.substring(1));
            }else if(s.startsWith("W") && s.substring(1).matches("[0-9]{1,2}")){
               y =  y + Integer.parseInt(s.substring(1));
            }else{
                continue;
            }
        }
        System.out.println( x + "," + y);
    }
}
发表于 2022-03-04 22:22:05 回复(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;
    }

发表于 2022-02-27 09:54:05 回复(0)
// 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;
}

发表于 2021-12-16 14:01:37 回复(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;
    }
}

发表于 2021-11-07 14:17:08 回复(0)
while True:
    try:
        n = input().split(";")
        coords = [0, 0]
        dic = {"A": [-1, 0], "D": [1, 0], "W": [0, 1], "S": [0, -1]}
        for i in n:
            if len(i)>=2:
                if (i[0] in dic) and i[1:].isdigit():
                    temp = [j * int(i[1:]) for j in dic[i[0]]]
                    coords = [x + y for x, y in zip(temp, coords)]
        print(str(coords[0]) + "," + str(coords[1]))
    except:
        break


发表于 2021-11-07 01:55:24 回复(0)
    这道题的思路有以下几个步骤:
    1.用strtok函数将字符串进行分割,分隔符为";"
    2.对于分割得到的字符串进行处理,首先是要判断它的有效性。如果分割出来的字符串长度小于2的话,说明是无效的子字符串;如果str[1]~str[len-1]有非数字的字符,那也可以判断为无效的子字符串
    3.接着就根据str[0]的值来进行具体的坐标移动操作,用atoi函数将&str[1]开始的字符串转换为数字
#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;
}


发表于 2021-10-09 14:45:45 回复(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);
}

发表于 2021-09-18 21:20:01 回复(0)
#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;
}

发表于 2021-09-07 14:45:39 回复(0)
using System;
using System.Collections;
namespace Test
{
    public class Program
    {
        public static void Main()
        {
            string str = null;
            while((str = Console.ReadLine())!=null)
            {
                var array = str.Split(';');
                int x = 0;
                int y = 0;
                for(int i=0; i<array.Length-1; i++)
                {
                    if(array[i].Length==3||array[i].Length==2)
                    {
                        if(array[i].Substring(0,1) == "A")
                        {
                            if(int.TryParse(array[i].Substring(1),out int result))
                            x-=result;
                        }
                        else if(array[i].Substring(0,1) == "D")
                        {
                            if(int.TryParse(array[i].Substring(1),out int result))
                            x+=result;
                        }
                        else if(array[i].Substring(0,1) == "W")
                        {
                            if(int.TryParse(array[i].Substring(1),out int result))
                            y+=result;
                        }
                        else if(array[i].Substring(0,1) == "S")
                        {
                            if(int.TryParse(array[i].Substring(1),out int result))
                            y-=result;
                        }
                    }
                }
                Console.WriteLine("{0},{1}", x, y);
            }
        }
    }
}
发表于 2021-08-24 19:04:24 回复(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

发表于 2021-06-12 10:16:22 回复(0)
代码量比较小的一个方案,而且用时和用内存都不高。
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);
        }
    }
}
编辑于 2021-05-11 00:12:51 回复(0)
分享一个简单的python思路,输入项中可以用try来过滤掉干扰项,剩下的就比较简单了,该加加,该减减
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))

发表于 2021-04-03 11:30:26 回复(0)
直接进行模拟,对于某个移动字符串,我们遍历其字符,将每个字母和连续的数字字符看作是一个单元。在字符串长度大于1,首字符为合法方向字母(WSAD),且尾字符为数字的情况下,有如下两种情况:
(1) 如果遇到的字符是方向字母WSAD,且上一个单元不是字母,就计算上一次需要往哪个方向移动多少步;否则两个字母连续出现,这个移动字符串无效。
(2) 如果遇到的字符是数字,就计算移动的步数。
遍历完字符串后,由于一个有效的移动字符串不会以字母字符结尾,按照上面的流程,我们是遍历到下一个方向字母时才会计算上一次移动所带来的坐标改变,因此需要额外再计算一下最后一次操作的移动,否则少一次移动。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    static int x, y;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line;
        while((line = br.readLine()) != null){
            String[] ops = line.split(";");
            x = 0;
            y = 0;
            for(int i = 0; i < ops.length; i++)
                move(ops[i].toCharArray());
            System.out.println(x + "," + y);
        }
    }
    
    private static void move(char[] op) {
        int rawX = x;
        int rawY = y;
        if(op.length <= 1) return;
        // 最后一个字符不是数字
        if(op[op.length - 1] < '0' || op[op.length - 1] > '9') return;
        // 第一个字符不是方向字母
        if(op[0] != 'A' && op[0] != 'S' && op[0] != 'D' && op[0] != 'W') return;
        int opPos = 0;
        int steps = 0;
        boolean flag = false;      // 上一个单元是字母
        int i = 0;
        while(i < op.length){
            if(op[i] >= '0' && op[i] <= '9'){
                steps = steps*10 + (op[i] - '0');
                flag = false;
            }else{
                // 上一次移动操作
                if(flag) break;     // 连续出现两个字母,无效
                if(op[0] != 'A' && op[0] != 'S' && op[0] != 'D' && op[0] != 'W') break;
                if(op[opPos] == 'A'){
                    x -= steps;
                }else if(op[opPos] == 'D'){
                    x += steps;
                }else if(op[opPos] == 'S'){
                    y -= steps;
                }else if(op[opPos] == 'W'){
                    y += steps;
                }
                steps = 0;
                opPos = i;
                flag = true;
            }
            i ++;
        }
        if(i != op.length){
            // 非正常退出,坐标还原
            x = rawX;
            y = rawY;
        }else{
            // 最后一次移动操作
            if(op[opPos] == 'A'){
                x -= steps;
            }else if(op[opPos] == 'D'){
                x += steps;
            }else if(op[opPos] == 'S'){
                y -= steps;
            }else if(op[opPos] == 'W'){
                y += steps;
            }
        }
    }
}


发表于 2021-03-20 18:11:39 回复(0)

感觉题目没说清楚,就是那个空格出现的位置,好多玩家似乎都没考虑,比如 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;
}
发表于 2021-02-25 21:59:12 回复(0)

问题信息

难度:
1788条回答 97371浏览

热门推荐

通过挑战的用户

查看代码
坐标移动