Developing Myself Everyday
Published 2023. 5. 17. 12:12
9019번: DSLR - Kotlin 카테고리 없음
 

9019번: DSLR

네 개의 명령어 D, S, L, R 을 이용하는 간단한 계산기가 있다. 이 계산기에는 레지스터가 하나 있는데, 이 레지스터에는 0 이상 10,000 미만의 십진수를 저장할 수 있다. 각 명령어는 이 레지스터에

www.acmicpc.net

문제

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

  1. D: D 는 n을 두 배로 바꾼다. 결과 값이 9999 보다 큰 경우에는 10000 으로 나눈 나머지를 취한다. 그 결과 값(2n mod 10000)을 레지스터에 저장한다.
  2. S: S 는 n에서 1 을 뺀 결과 n-1을 레지스터에 저장한다. n이 0 이라면 9999 가 대신 레지스터에 저장된다.
  3. L: L 은 n의 각 자릿수를 왼편으로 회전시켜 그 결과를 레지스터에 저장한다. 이 연산이 끝나면 레지스터에 저장된 네 자릿수는 왼편부터 d2, d3, d4, d1이 된다.
  4. 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 이 된다.

입력

프로그램 입력은 T 개의 테스트 케이스로 구성된다. 테스트 케이스 개수 T 는 입력의 첫 줄에 주어진다. 각 테스트 케이스로는 두 개의 정수 A와 B(A ≠ B)가 공백으로 분리되어 차례로 주어지는데 A는 레지스터의 초기 값을 나타내고 B는 최종 값을 나타낸다. A 와 B는 모두 0 이상 10,000 미만이다.

출력

A에서 B로 변환하기 위해 필요한 최소한의 명령어 나열을 출력한다. 가능한 명령어 나열이 여러가지면, 아무거나 출력한다.

 

나의 풀이 - 1차 (시간초과)

 이 문제는 생각보다 단순한 문제이다. 시간이 꽤 넉넉함으로 무차별적으로 숫자를 d,s,l,r을 돌려서 가장 먼저 B에 도달했을 때를 출력하면 되는 문제이다. 다만 시간이 넉넉하다고 단순하게 생각하면 무조건 시간초과가 난다. 그래서 이 문제를 해결하려면 어떻게 하면 시간을 줄일 것인가를 생각하는게 가장 중요하다.

 

 아래와 같이 최대한 시간을 줄여보려고 했으나 시간초과가 발생하고 말았다.

import java.lang.Math.log10
import java.lang.Math.pow
import java.util.LinkedList
import java.util.Queue
import kotlin.math.pow

fun main() = with(System.`in`.bufferedReader()) {
    val t = readLine().toInt()

    val ex = Array(t) { readLine().split(" ").map { it.toInt() } }

    ex.forEach {
        bfs(it[0], it[1])
    }
}

fun bfs(A: Int, B: Int) {
    val queue: Queue<Pair<Int, String>> = LinkedList()
    val visited = BooleanArray(10000) { false }
    queue.add(A to "")

    while (queue.isNotEmpty()) {
        val (num, answer) = queue.poll()

        if (num == B) {
            println(answer)
            return
        }

        val d = d(num)
        val s = s(num)
        val l = l(num)
        val r = r(num)

        if (!visited[d]) {
            visited[d] = true
            queue.add(d to answer + "D")
        }
        if (!visited[s]) {
            visited[s] = true
            queue.add(s to answer + "S")
        }
        if (!visited[l]) {
            visited[l] = true
            queue.add(l to answer + "L")
        }
        if (!visited[r]) {
            visited[r] = true
            queue.add(r to answer + "R")
        }
    }
}

fun d(A: Int): Int {
    return (A * 2) % 10000
}

fun s(A: Int): Int {
    if (A == 0)
        return 9999
    else
        return A - 1
}

fun l(A: Int): Int {
    val numDigits = (log10(A.toDouble()) + 1).toInt()
    val firstDigit = A / pow(10.0, (numDigits - 1).toDouble()).toInt()
    return (A - firstDigit * pow(10.0, (numDigits - 1).toDouble()).toInt()) * 10 + firstDigit
}

fun r(A: Int): Int {
    return (A / 10) + ((A % 10) * (10.0.pow((A.toString().length - 1).toDouble())).toInt())
}

 

 

나의 풀이 - 2차 

 나의 코드의 문제점은 바로 숫자의 자릿수를 회전시키는 부분이었다. 나는 숫자의 자릿수를 계산한 다음 문제를 숫자를 회전시켰는데, 이 문제에는 숫자의 자릿수가 4자리로 고정된다는 것이었다. 123이란 숫자가 있어도 0123 이런식으로 저장이 된다는 것이다.

 

fun l(A: Int): Int {
    return (A % 1000) * 10 + A / 1000
}

fun r(A: Int): Int {
    return (A % 10) * 1000 + (A / 10) % 1000
}

 

import java.lang.Math.log10
import java.lang.Math.pow
import java.util.LinkedList
import java.util.Queue
import kotlin.math.pow

fun main() = with(System.`in`.bufferedReader()) {
    val t = readLine().toInt()

    val ex = Array(t) { readLine().split(" ").map { it.toInt() } }

    ex.forEach {
        bfs(it[0], it[1])
    }
}

fun bfs(A: Int, B: Int) {
    val queue: Queue<Pair<Int, String>> = LinkedList()
    val visited = BooleanArray(10000) { false }
    queue.add(A to "")

    while (queue.isNotEmpty()) {
        val (num, answer) = queue.poll()

        if (num == B) {
            println(answer)
            return
        }

        val d = d(num)
        val s = s(num)
        val l = l(num)
        val r = r(num)

        if (!visited[d]) {
            visited[d] = true
            queue.add(d to answer + "D")
        }
        if (!visited[s]) {
            visited[s] = true
            queue.add(s to answer + "S")
        }
        if (!visited[l]) {
            visited[l] = true
            queue.add(l to answer + "L")
        }
        if (!visited[r]) {
            visited[r] = true
            queue.add(r to answer + "R")
        }
    }
}

fun d(A: Int): Int {
    return (A * 2) % 10000
}

fun s(A: Int): Int {
    if (A == 0)
        return 9999
    else
        return A - 1
}

fun l(A: Int): Int {
    return (A % 1000) * 10 + A / 1000
}

fun r(A: Int): Int {
    return (A % 10) * 1000 + (A / 10) % 1000
}
profile

Developing Myself Everyday

@배준형

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!