[PS] 포도주 시식 (백준 2156번)
역시 Dynamic Programming
문제는 점화식을 잘 세우는게 정말 중요하다.
이거에 따라 풀 수 있는 문제인지, 절대 못 푸는 문제인지 정해지니까..
그리고 무의식적으로 Java
로 코테를 준비할 때는 속도를 위해 모든 필드와 메서드를 static
으로 선언해서 사용해왔다.
보다 객체지향적으로 짜려고 데이터 입력받는 책임을 수행하는 Reader
클래스를 따로 구현했는데(FastCampus 강의를 수강하며 참고함), 내부 클래스에도 static
을 꼭 선언해야 하나 해서 읽던 Effective Java
를 다시 폈다.
내부 클래스를 구현할 때는 내부 클래스가 외부 클래스에게 위임하거나 호출하는게 없다면, static
으로 구현하라고 나와있다.
가장 큰 이유는, static
으로 구현하지 않는다면 외부 클래스로 부터 내부 클래스의 인스턴스가 외부 참조가 생기기 때문에, 추가적인 메모리 사용하기도 하며 더 나아가 GC(Garbage Collector)
가 참조 메모리를 찾지 못해서 해당 메모리를 처리할 수 없다는 것이다.
static
으로 사용하지 않는 경우는 다양하지만, 이는 적어도 코테에서는 크게 신경쓸 필요는 없는 것 같다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
/* BOJ no.2156 - 포도주와 시식 (DP) */
public class Main {
static int N;
static int[] grapeJuiceAmounts;
static int[] amountsNotDrinkLast;
static int[] amountsDrinkLast;
static int amountMaximumDrink;
public static void main(String[] args) {
input();
calculateMaximumDrink();
printResult();
}
static void printResult() {
System.out.println(amountMaximumDrink);
}
static void calculateMaximumDrink() {
int size = N + 1;
for (int idx = 3; idx < size; idx++) {
amountsNotDrinkLast[idx] = Math.max(amountsNotDrinkLast[idx - 1], amountsDrinkLast[idx - 1]);
amountsDrinkLast[idx] = Math.max(amountsNotDrinkLast[idx - 2] + grapeJuiceAmounts[idx - 1] + grapeJuiceAmounts[idx]
, amountsDrinkLast[idx - 2] + grapeJuiceAmounts[idx]);
}
amountMaximumDrink = Math.max(amountsNotDrinkLast[N], amountsDrinkLast[N]);
}
static void input() {
Reader reader = new Reader();
N = reader.readInt();
int size = N + 1;
grapeJuiceAmounts = new int[size];
amountsNotDrinkLast = new int[size];
amountsDrinkLast = new int[size];
for (int idx = 1; idx < size; idx++) {
grapeJuiceAmounts[idx] = reader.readInt();
}
amountsNotDrinkLast[1] = 0;
amountsDrinkLast[1] = grapeJuiceAmounts[1];
if (N > 1) {
amountsNotDrinkLast[2] = grapeJuiceAmounts[1];
amountsDrinkLast[2] = grapeJuiceAmounts[1] + grapeJuiceAmounts[2];
}
}
static class Reader {
BufferedReader bufferedReader;
StringTokenizer stringTokenizer;
Reader() {
bufferedReader = new BufferedReader(new InputStreamReader(System.in));
}
String read() {
while (stringTokenizer == null || !stringTokenizer.hasMoreElements()) {
try {
stringTokenizer = new StringTokenizer(bufferedReader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return stringTokenizer.nextToken();
}
int readInt() {
return Integer.parseInt(read());
}
}
}