Algorithm/Algorithm Problem

백준 17939번: Gazzzua(Python/Java)

주유소짜글이 2022. 2. 11. 10:32

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

 

17939번: Gazzzua

최대의 수익을 얻으려면, 일단 가격이 1, 5일 때 1개씩 사서 10일 때 샀던 코인 2개를 다 팔고, 이어서 가격이 2일 때 1개를 사고 4일 때 판다. 이 경우, 총 (10-1) + (10-5) + (4-2) = 16의 수익을 얻을 수 있

www.acmicpc.net

 

 

 

접근


실제 가상화폐든, 그리디 알고리즘의 가상화폐든 이득을 얻는 방법은 간단하다. 저점에서 사고 고점에서 파는 것이다. 만고불변의 진리. 그렇다면 이 문제는 어떻게 해결해야 할까? 저점에서 사고 고점에서 팔면 되지!!

 

우선 현재 주어진 값들 중에서 높은 값이 어디 있는지 확인한다. 그 고점이 나오기 전까지는 무조건 매입한다. 왜냐? 해당 고점보다 낮으면 얼마나 사들었는지 무조건 이득이기 때문이다. 해당 고점이 나오면 매입한 모든 코인을 판다. 그럼 이제부터 다시 확인해보자. 코인을 판 칸의 다음 칸부터 마지막 값까지 가장 높은 값을 찾는다. 그 뒤 또 가장 높은 값이 나올 때까지 매입한 뒤, 가장 높은 값에서 판다. 이를 계속 반복한다. 이렇게 하면 절대 손해보지 않고 코인을 사고팔 수 있게 된다.

 

 

 

풀이


Python

coinNum = int(input())
board = list(map(int, (input()).split()))

sumNum = 0
result = 0
subResult = 0
maxNum = max(board)
for i in range(coinNum):
    if board[i] < maxNum:
        subResult += board[i]
        sumNum += 1
    else:
        result += (maxNum*sumNum - subResult)
        if i != (coinNum-1):
            maxNum = max(board[i+1:])
        sumNum = 0
        subResult = 0

print(result)

 

Java

import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;

public class Main {
    
    public static void main(String[] args) {
        
        Scanner scan = new Scanner(System.in);
        
        int coinNum = Integer.parseInt(scan.nextLine());
        String[] firstLine = (scan.nextLine()).split(" ");
        Integer[] board = new Integer[coinNum];
        Integer[] sortedBoard = new Integer[coinNum];
        int maxNum = 0;
        for(int i = 0 ; i < coinNum ; i++){
            board[i] = Integer.parseInt(firstLine[i]);
            maxNum = Math.max(maxNum, board[i]);
        }
        int subNum = 0, result = 0, subResult = 0;
        for(int i = 0 ; i < coinNum ; i++){
            if(board[i] < maxNum){
                subResult += board[i];
                subNum++;
            }else{
                result += (maxNum*subNum - subResult);
                if(i != (coinNum-1)){
                    maxNum = 0;
                    for(int j = (i+1) ; j < coinNum ; j++){
                        maxNum = Math.max(maxNum, board[j]);
                    }
                }
                subNum = 0;
                subResult = 0;
            }
        }

        System.out.println(result);
    }

}

 

 

 

후기


물론 정답에는 큰 영향을 미치지 않았을 것이긴 하지만 실수가 있었던 문제. java로 해결할 때, 처음 배열 내에서 가장 큰 값을 찾을 시, 그냥 배열에 값을 넣는 과정에서 찾아주면 되는데 굳이 배열을 정렬하고 그 뒤에 가장 앞의 값을 꺼냈었다. 풀다 보니 '내가 무슨 멍청한 짓을...'하고 호다닥 수정했다.

 

중요한 것은 결과적으로는 같은 값을 도출하더라도 조금 더 연산이 적고, 조금 더 효율적인 코드를 작성하는 것!!