코딩 테스트(Coding Test)/백준

[백준 20546번] 기적의 매매법

배씌 2024. 11. 26. 13:49

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


문제


아이디어

문제가 길지만 요약하자면 아래와 같다.

 

준현 (BNP)

  • 매수가 가능한 경우, 최대한 많이 산다.

성민 (TIMING)

  • 모든 거래 : 전량 매수/ 전량 매도
  • 3일 연속 가격 상승(무조건 올랐을 때만) -> 3일째에 전량 매도
  • 3일 연속 가격 하락(무조건 내렸을 때만) -> 3일째에 전량 매수

최종 자산 : 보유 현금 + (주가 x 보유 주식 개수)

 

문제의 조건을 보면, 거래 기간도 14일이므로 시간 복잡도는 따로 고려할 필요 없이 구현만 정확히 해내면 되는 문제라고 생각했다.

 

- 준현

Greedy 하게 해결이 가능하다. 배열의 첫 원소부터 구입이 가능하다면 최대한 구입후, 보유 현금 + 보유 주식 개수 * 마지막 날 주가 가 정답이다.

// 준현 매매법 - BNP
static int BNP(int seedMoney, int[] stocks) {
    // 매수한 주식 개수
    int count = 0;
    for (int stock : stocks) {
        // 시드머니 떨어지면 즉시 종료
        if(seedMoney == 0) break;

        // 시드머니로 주식 구매 가능하다면, 최대한 매수
        if (stock <= seedMoney) {
            int nowCount = (seedMoney / stock);
            seedMoney -= (stock * nowCount);
            count += nowCount;
        }
    }
    return seedMoney + count * stocks[13];
}

 

- 성민

성민은 주가가 상승할 때와, 하락할 때를 고려해서 작성해야 한다. 상승, 하락도 3일을 연속으로 해야하니, 각각 체크할 수 있는 변수를 만들어 상승과 하락을 기록했다.

// 성민 매매법 - TIMING
static int TIMING(int seedMoney, int[] stocks) {
    int count = 0;  // 매수한 주식 개수
    int checkUp = 0;    // 3일 연속 상승하는지 확인용
    int checkDown = 0;  // 3일 연속 하락하는지 확인용
    for(int i=1; i<stocks.length; i++) {
        // 주가가 하락할 때
        if(stocks[i-1] > stocks[i]) {
            checkDown++;
            checkUp = 0;
            // 3일 연속 하락했고, 시드머니로 주식을 살 수 있으면 구매
            if(checkDown >= 3 && seedMoney >= stocks[i]) {
                int nowCount = (seedMoney / stocks[i]);
                seedMoney -= (stocks[i] * nowCount);
                count += nowCount;
            }
        }
        // 주가가 상승할 때
        else if(stocks[i-1] < stocks[i]) {
            checkUp++;
            checkDown = 0;
            // 3일 연속 상승했고, 보유 주식이 있으면 모두 판매
            if(checkUp >= 3 && count > 0) {
                seedMoney += (count * stocks[i]);
                count = 0;
                checkUp = 0;
            }
        }
    }
    return seedMoney + count * stocks[13];
}

전체 코드

package IntStudy;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class B_20546 {
    // 준현 매매법 - BNP
    static int BNP(int seedMoney, int[] stocks) {
        // 매수한 주식 개수
        int count = 0;
        for (int stock : stocks) {
            // 시드머니 떨어지면 즉시 종료
            if(seedMoney == 0) break;

            // 시드머니로 주식 구매 가능하다면, 최대한 매수
            if (stock <= seedMoney) {
                int nowCount = (seedMoney / stock);
                seedMoney -= (stock * nowCount);
                count += nowCount;
            }
        }
        return seedMoney + count * stocks[13];
    }
    // 성민 매매법 - TIMING
    static int TIMING(int seedMoney, int[] stocks) {
        int count = 0;  // 매수한 주식 개수
        int checkUp = 0;    // 3일 연속 상승하는지 확인용
        int checkDown = 0;  // 3일 연속 하락하는지 확인용
        for(int i=1; i<stocks.length; i++) {
            // 주가가 하락할 때
            if(stocks[i-1] > stocks[i]) {
                checkDown++;
                checkUp = 0;
                // 3일 연속 하락했고, 시드머니로 주식을 살 수 있으면 구매
                if(checkDown >= 3 && seedMoney >= stocks[i]) {
                    int nowCount = (seedMoney / stocks[i]);
                    seedMoney -= (stocks[i] * nowCount);
                    count += nowCount;
                }
            }
            // 주가가 상승할 때
            else if(stocks[i-1] < stocks[i]) {
                checkUp++;
                checkDown = 0;
                // 3일 연속 상승했고, 보유 주식이 있으면 모두 판매
                if(checkUp >= 3 && count > 0) {
                    seedMoney += (count * stocks[i]);
                    count = 0;
                    checkUp = 0;
                }
            }
        }
        return seedMoney + count * stocks[13];
    }
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 시드머니, 주가 입력
        int seedMoney = Integer.parseInt(br.readLine());
        int[] stocks = new int[14];
        StringTokenizer st = new StringTokenizer(br.readLine());
        for(int i=0; i<stocks.length; i++) {
            stocks[i] = Integer.parseInt(st.nextToken());
        }
        int res1 = BNP(seedMoney, stocks);
        int res2 = TIMING(seedMoney, stocks);
        if(res1 == res2)
            System.out.println("SAMESAME");
        else
            System.out.println(res1 > res2 ? "BNP" : "TIMING");
    }
}