본문 바로가기
알고리즘 문제 풀이/백준

백준 Byte Coin 17251 Kotlin (그리디)

by 옹구스투스 2022. 2. 9.
반응형

문제 출처 : https://www.acmicpc.net/problem/17521

 

17521번: Byte Coin

입력은 표준입력을 사용한다. 첫 번째 줄에 요일 수를 나타내는 양의 정수 n과 초기 현금 W(1 ≤ n ≤ 15, 1 ≤ W ≤ 100,000)가 주어진다. 다음 n 개의 줄에서, i번째 줄은 i일의 바이트 코인 가격을 나

www.acmicpc.net

문제

국제자본부동산회사(ICPC)는 바이트 코인(Byte Coin)에 자금을 투자하고 있다. 바이트 코인은 김박사가 만든 가상 화폐이다. 실제로는 바이트 코인 가격을 예상할 수 없지만 이 문제에서는 바이트 코인 가격 등락을 미리 정확히 예측할 수 있다고 가정하자.

우리는 1일부터 n일까지 n일 동안 그림 1과 같이 바이트 코인의 등락을 미리 알 수 있으며 우리에게는 초기 현금 W가 주어져 있다. 그림 1의 빨간색 네모는 해당 일자의 바이트 코인 가격을 나타낸다. 매일 바이트 코인을 매수하거나 매도할 수 있다고 하자. 다만 바이트 코인 하나를 나누어 매도하거나 매수할 수는 없다. 우리는 n일 날 보유하고 있는 모든 코인을 매도할 때 가지고 있는 현금을 최대화하고 싶다. 

그림 1. 10 일간 바이트 코인 가격 등락 그래프

예를 들어, 그림 1과 같은 바이트 코인 등락 그래프를 첫날 미리 알 수 있다고 하고 우리에게 주어진 초기 현금이 24라고 하자. 수익을 최대한 높이려면 다음과 같이 바이트 코인을 매수, 매도할 수 있다. 첫 날 현금 20을 써서 4개의 코인을 산다. 둘째 날 모든 코인을 매도해서 현금 28을 얻고 모두 32의 현금을 갖게 된다. 5일째 되는 날 현금 32를 써서 16개의 코인을 매수한다. 7일째 되는 날 모든 코인을 매도해서 모두 128의 현금을 갖게 된다. 9일째 되는 날 현금 126을 써서 42개의 코인을 사고 10일 날 모든 코인을 매도한다. 그러면 10일 날 현금이 170이 되고 이것이 최대이다.

요일 수 n, 초기 현금 W, 1일부터 n일까지 각 요일의 바이트 코인 가격이 주어질 때, n일 날 보유하고 있는 모든 코인을 매도할 때 보유하게 될 최종 현금의 최댓값을 출력하는 프로그램을 작성하시오.

입력

입력은 표준입력을 사용한다. 첫 번째 줄에 요일 수를 나타내는 양의 정수 n과 초기 현금 W(1 ≤ n ≤ 15, 1 ≤ W ≤ 100,000)가 주어진다. 다음 n 개의 줄에서, i번째 줄은 i일의 바이트 코인 가격을 나타내는 정수 si가 주어진다(1 ≤ si ≤ 50).

출력

출력은 표준출력을 사용한다. n일 날 보유하고 있는 모든 코인을 매도할 때 가지고 있는 현금의 최댓값을 한 행에 출력한다. 비록 초기 현금 W는 그렇게 크지 않지만 최종 현금은 매우 커질 수 있음에 주의하자.

알고리즘 분류

풀이

어려운 규칙 필요 없이 그저 고점에 팔고 저점에 사는 것만 잘 구현하면 된다.

주식을 어제의 가격으로 구매하고 팔 수 있다고 생각하자.(너무 행복하다...)

어제의 주가가 오늘보다 낮다면 어제는 무조건 저점이다. 어제의 주식 가격으로 구매하자.

오제의 주가가 오늘보다 높다면 어제는 무조건 고점이다. 어제의 주식 가격으로 판매하자.

이 규칙만 지킨다면 상승장이 시작되는 순간 상승 전의 가격으로 구매하고,

하락장이 시작되는 순간 하락 전의 가격으로 판매하기 때문에, 연속된 하락장에선 이미 털고 나와서 팔지 않게 된다.

코인아 좀 올라라

 

코드

val br = System.`in`.bufferedReader()

fun main() = with(System.out.bufferedWriter()) {

    var (n, w) = br.readLine().split(' ').map { it.toLong() }
    val cost = LongArray(n.toInt())
    cost[0] = br.readLine().toLong()
    var stockCnt = 0L

    for (i in 1 until n.toInt()) {
        cost[i] = br.readLine().toLong()
        //상승장
        if (cost[i - 1] < cost[i]) {
            //저점 매수
            if(stockCnt==0L) {
                stockCnt = w / cost[i - 1]
                w %= cost[i - 1]
            }
            //마지막 날
            if (i == n.toInt() - 1) {
                //남은 주식 매도
                if (stockCnt > 0) {
                    w += stockCnt * cost[i]
                }
            }
        }
        //하락장
        else {
            //고점 매도
            w += cost[i - 1] * stockCnt
            stockCnt = 0L
        }
    }
    write("$w")

    close()
}
반응형

댓글