궤도

[백준] 5430번 : AC 본문

💻 현생/⛓ 알고리즘

[백준] 5430번 : AC

영이오 2021. 3. 26. 19:44

문제

 


풀이

 

문제 자체도 시간초과 때문에 아주 만만한 문제는 아닌데 입력이 아주 재미나게 들어와서 난이도를 더하는 문제다.

문제의 제목은 입력을 처리하다 나오는 말을 쓴 것 아닐까?

 

아무튼 시간초과를 보고 싶지 않다면, 이걸 생각하면 된다.

R이 나왔을 때 꼭 배열을 뒤집을 필요는 없다.

 

한 수열에 대해 뒤에서부터 출력하면 reverse한 수열을 앞에서부터 출력하는 거랑 다를게 없다.


소스코드

 

#include <iostream>
#include <deque>
#include <string>
using namespace std;

int main() {
    cin.tie(NULL);
    ios_base::sync_with_stdio(false);
    string p, arr;
    int T, n;

    cin >> T;
    for (int i = 0; i < T; i++) {
        cin >> p >> n;
        deque <int> dq;
        cin >> arr;
        string temp; //2자리 이상일 때
        for (int j = 0; j < arr.length(); j++) {
            if ('0' <= arr[j] && arr[j] <= '9') //숫자면 저장
                temp += arr[j];
            else if (arr[j] == ',' || arr[j] == ']') { //쉼표나 괄호 만나면 전부 빼냄
                if (!temp.empty()) {
                    dq.push_back(stoi(temp)); //stoi 쓰려면 c++11로 써야함
                    temp.clear();
                }
            }
        }
        bool isError = false; //에러확인
        bool isFront = true; //reverse 확인
        for (int j = 0; j < p.length(); j++) {
            if (p[j] == 'R') { //현재 상태에서 reverse
                if (isFront)
                    isFront = false;
                else
                    isFront = true;
            }
            else if (p[j] == 'D') {
                if (dq.empty()) { //덱이 비어 있으면 에러
                    cout << "error\n";
                    isError = true;
                    break;
                }
                else if (isFront) //reverse 상태에 따라 pop
                    dq.pop_front();
                else
                    dq.pop_back();
            }
        }
        if (!isError) {
            cout << "[";
            if (isFront) { //앞에서부터 출력
                while (!dq.empty()) {
                    cout << dq.front();
                    dq.pop_front();
                    if (!dq.empty())
                        cout << ",";
                }
            }
            else { //뒤에서부터 출력
                while (!dq.empty()) {
                    cout << dq.back();
                    dq.pop_back();
                    if (!dq.empty())
                        cout << ",";
                }
            }
            cout << "]\n";
        }
    }
}

전체 소스코드다.

 

        cin >> p >> n;
        deque <int> dq;
        cin >> arr;
        string temp; //2자리 이상일 때
        for (int j = 0; j < arr.length(); j++) {
            if ('0' <= arr[j] && arr[j] <= '9') //숫자면 저장
                temp += arr[j];
            else if (arr[j] == ',' || arr[j] == ']') { //쉼표나 괄호 만나면 전부 빼냄
                if (!temp.empty()) {
                    dq.push_back(stoi(temp)); //stoi 쓰려면 c++11이상으로 써야함
                    temp.clear();
                }
            }
        }

입력을 처리하는 부분이다.

[1,2,3,4] 이런식으로 들어온 값을 string arr에 넣어주고 앞에서부터 조회하며 숫자라면 string temp에 넣어준다.

왜 바로 숫자로 바꿔서 덱에 넣는 것이 아니라 temp에 저장하냐면 42같은 두자리 이상의 수가 들어올 수도 있기 때문이다.

쉼표나 오른쪽 괄호를 만나면 temp에 저장된 숫자를 int로 바꿔줘야 하는데 이때 stoi 함수를 사용한다.

 

www.cplusplus.com/reference/string/stoi/?kw=stoi

 

stoi - C++ Reference

function template std::stoi int stoi (const string& str, size_t* idx = 0, int base = 10); int stoi (const wstring& str, size_t* idx = 0, int base = 10); Convert string to integer Parses str interpreting its content as an integral number of the spe

www.cplusplus.com

단순히 string 변수만 인자로 넣어줄 땐 10진수로 바꾸겠단 뜻이다.

 

        bool isError = false; //에러확인
        bool isFront = true; //reverse 확인
        for (int j = 0; j < p.length(); j++) {
            if (p[j] == 'R') { //현재 상태에서 reverse
                if (isFront)
                    isFront = false;
                else
                    isFront = true;
            }
            else if (p[j] == 'D') {
                if (dq.empty()) { //덱이 비어 있으면 에러
                    cout << "error\n";
                    isError = true;
                    break;
                }
                else if (isFront) //reverse 상태에 따라 pop
                    dq.pop_front();
                else
                    dq.pop_back();
            }
        }

이 수열이 지금 정방향인지 역방향인지 알기위해 isFront 변수를 뒀다. 당연히 초기값은 true다.

R을 만나면 isFront의 값을 현재 값의 반대로 만든다.

D를 만나면 덱이 비어있는지 확인하고 비어있다면 error를 반환한다. 만약 덱이 비어있지 않다면 isFront를 확인한다.

true값이면 정방향이니 맨 앞의 값을 빼주고, false값이면 역방향이니 맨 뒤의 값을 뺴준다.

 

        if (!isError) {
            cout << "[";
            if (isFront) { //앞에서부터 출력
                while (!dq.empty()) {
                    cout << dq.front();
                    dq.pop_front();
                    if (!dq.empty())
                        cout << ",";
                }
            }
            else { //뒤에서부터 출력
                while (!dq.empty()) {
                    cout << dq.back();
                    dq.pop_back();
                    if (!dq.empty())
                        cout << ",";
                }
            }
            cout << "]\n";
        }

에러없이 모든 연산을 수행했다면 isFront의 값에 따라 앞에서부터 출력하거나 뒤에서부터 출력한다.

Comments