[백준] 9019번 DSLR Javascript(NodeJs)

JeongYong·2022년 10월 28일
0

Algorithm

목록 보기
48/263

문제 링크

https://www.acmicpc.net/problem/9019

알고리즘: BFS

문제

네 개의 명령어 D, S, L, R 을 이용하는 간단한 계산기가 있다. 이 계산기에는 레지스터가 하나 있는데, 이 레지스터에는 0 이상 10,000 미만의 십진수를 저장할 수 있다. 각 명령어는 이 레지스터에 저장된 n을 다음과 같이 변환한다. n의 네 자릿수를 d1, d2, d3, d4라고 하자(즉 n = ((d1 × 10 + d2) × 10 + d3) × 10 + d4라고 하자)

D: D 는 n을 두 배로 바꾼다. 결과 값이 9999 보다 큰 경우에는 10000 으로 나눈 나머지를 취한다. 그 결과 값(2n mod 10000)을 레지스터에 저장한다.
S: S 는 n에서 1 을 뺀 결과 n-1을 레지스터에 저장한다. n이 0 이라면 9999 가 대신 레지스터에 저장된다.
L: L 은 n의 각 자릿수를 왼편으로 회전시켜 그 결과를 레지스터에 저장한다. 이 연산이 끝나면 레지스터에 저장된 네 자릿수는 왼편부터 d2, d3, d4, d1이 된다.
R: R 은 n의 각 자릿수를 오른편으로 회전시켜 그 결과를 레지스터에 저장한다. 이 연산이 끝나면 레지스터에 저장된 네 자릿수는 왼편부터 d4, d1, d2, d3이 된다.
위에서 언급한 것처럼, L 과 R 명령어는 십진 자릿수를 가정하고 연산을 수행한다. 예를 들어서 n = 1234 라면 여기에 L 을 적용하면 2341 이 되고 R 을 적용하면 4123 이 된다.

여러분이 작성할 프로그램은 주어진 서로 다른 두 정수 A와 B(A ≠ B)에 대하여 A를 B로 바꾸는 최소한의 명령어를 생성하는 프로그램이다. 예를 들어서 A = 1234, B = 3412 라면 다음과 같이 두 개의 명령어를 적용하면 A를 B로 변환할 수 있다.

1234 →L 2341 →L 3412
1234 →R 4123 →R 3412

따라서 여러분의 프로그램은 이 경우에 LL 이나 RR 을 출력해야 한다.

n의 자릿수로 0 이 포함된 경우에 주의해야 한다. 예를 들어서 1000 에 L 을 적용하면 0001 이 되므로 결과는 1 이 된다. 그러나 R 을 적용하면 0100 이 되므로 결과는 100 이 된다.

풀이

문제를 읽고 이게 왜 20퍼지? 의문을 품었다. 그런데 한 두 번 시간 초과를 겪고 아 이래서 20퍼구나 느꼈던 문제이다. 이 문제를 시간 초과 없이 통과 하기 위해서는 'L'과 'R'연산을 최소한으로 줄여야 한다.

1) 'L'연산은 왼쪽으로 회전하고 천의 자리가 일의 자리로 간다.
n = 1234라면 1234 나누기 1000은 몫이 1 나머지가 234 나온다.
234 * 10 + 1 = 2341이고 2341은 1234를 왼쪽으로 회전시킨 결괏값이다.

2) 'R'연산은 오른쪽으로 회전하고 일의 자리가 천의 자리로 간다.
n = 1234라면 1234 나누기 10은 몫이 123 나머지가 4가 나온다.
123 + 4 * 1000 = 4123이고 4123은 1234를 오른쪽으로 회전시킨 결괏값이다.

이 두 개 연산만 이렇게 줄일 수 있다면 통과할 수 있다.

소스코드

class Queue {
    constructor() {
        this.storage = {};
        this.front = 0;
        this.rear = -1;
    }

    size() {
        if (this.front > this.rear) {
            return 0;
        } else {
            return this.rear - this.front + 1;
        }
    }

    push(value) {
        this.rear += 1;
        this.storage[this.rear] = value;
    }

    pop_left() {
        let value = this.storage[this.front];
        if (this.size()) {
            delete this.storage[this.front];
            this.front += 1;
        }
        return value;
    }
}
const fs = require('fs');
let inputData = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
let T = inputData[0].trim() * 1;
let A;
let B;
let visited;
let output = '';
let op = ['D', 'S', 'L', 'R'];
for (let i = 1; i <= T; i++) {
    let [a, b] = inputData[i].trim().split(' ').map(x => x * 1);
    A = a;
    B = b;
    visited = new Array(10000).fill(false);
    output += `${BFS()}\n`;
}
console.log(output.trim());

function BFS() {
    let que = new Queue();
    que.push([A, '']);
    visited[A] = true;
    while (que.size()) {
        let [a, op_str] = que.pop_left();
        if (a === B) {
            return op_str;
        }
        for (let i = 0; i < op.length; i++) {
            let na = DSLR(a, op[i]);
            if (!visited[na]) {
                visited[na] = true;
                que.push([na, op_str + op[i]]);
            }
        }
    }
}

function DSLR(v, op) {
    let nv;
    if (op === 'D') {
        nv = v * 2;
        if (nv > 9999) {
            nv = nv % 10000;
        }
    } else if (op === 'S') {
        if (v === 0) {
            nv = 9999;
        } else {
            nv = v - 1;
        }
    } else if( op === 'L') {
        nv = v % 1000 * 10 + parseInt(v/1000);
    } else if( op === 'R') {
        nv = parseInt(v/10) + v % 10 * 1000
    }
    return nv;
}

0개의 댓글