코딩 테스트(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");
}
}