1. 문제 분석
🏆 문제 개요
2 × n
크기의 스티커 배열에서 점수를 최대로 얻도록 스티커를 선택해야 한다.- 단, 선택한 스티커와 변을 공유하는 스티커는 사용할 수 없다.
- 최대 점수를 출력하는 프로그램을 작성해야 한다.
🎯 요구사항
- 각 테스트 케이스에 대해 최대 점수를 출력해야 한다.
- 두 행(
2 × n
)으로 구성된 스티커 배열에서 인접하지 않은 스티커들을 선택해야 한다. 1 ≤ n ≤ 100,000
이므로, 효율적인 알고리즘이 필요하다. (시간 복잡도O(n)
이하)
2. 해결 방법
🔹 핵심 개념
이 문제는 다이나믹 프로그래밍(DP)을 활용하면 효과적으로 해결할 수 있다.
점화식을 세우는 것이 핵심이며, 각 위치에서 얻을 수 있는 최대 점수를 누적해 나가는 방식이다.
🔑 해결 절차
- 입력값 처리 및 DP 테이블 초기화
sticker[2][n]
배열을 입력받아 스티커 점수를 저장한다.dp[2][n]
배열을 사용하여 해당 위치까지의 최대 점수를 저장한다.
- DP 점화식 세우기
- 기본 아이디어:
dp[i][j] = max(이전 행의 선택 가능 칸 + 현재 칸 점수)
dp[0][j] = max(dp[1][j-1], dp[1][j-2]) + sticker[0][j]
dp[1][j] = max(dp[0][j-1], dp[0][j-2]) + sticker[1][j]
- 기본 아이디어:
- 최종 출력
Math.max(dp[0][n-1], dp[1][n-1])
값 출력.
3. 코드 구현
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine()); // 테스트 케이스 개수
for (int t = 0; t < T; t++) {
int n = Integer.parseInt(br.readLine()); // 스티커 개수
int[][] sticker = new int[2][n];
int[][] dp = new int[2][n];
// 스티커 점수 입력
StringTokenizer st;
for (int i = 0; i < 2; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < n; j++) {
sticker[i][j] = Integer.parseInt(st.nextToken());
}
}
// DP 초기값 설정
dp[0][0] = sticker[0][0];
dp[1][0] = sticker[1][0];
if (n > 1) {
dp[0][1] = sticker[1][0] + sticker[0][1];
dp[1][1] = sticker[0][0] + sticker[1][1];
}
// DP 점화식 적용
for (int j = 2; j < n; j++) {
dp[0][j] = Math.max(dp[1][j-1], dp[1][j-2]) + sticker[0][j];
dp[1][j] = Math.max(dp[0][j-1], dp[0][j-2]) + sticker[1][j];
}
// 최대 점수 출력
System.out.println(Math.max(dp[0][n-1], dp[1][n-1]));
}
}
}
4. 코드 분석
🔹 주요 알고리즘
- 입력 처리 & 초기화
sticker[2][n]
배열에 점수 입력dp[2][n]
배열을 생성하여 각 칸까지의 최대 점수 저장
- DP 점화식 적용
- 초기값 설정 (
dp[0][0]
,dp[1][0]
,dp[0][1]
,dp[1][1]
) j ≥ 2
부터 점화식을 적용하여 최대 점수를 누적 계산
- 초기값 설정 (
- 최종 출력
dp[0][n-1]
과dp[1][n-1]
중 큰 값 출력
🔹 시간 복잡도 분석
- 입력 처리:
O(n)
- DP 연산:
O(n)
- 총 시간 복잡도:
O(n)
n ≤ 100,000
이므로 충분히 빠르게 동작한다.
5. 개선할 점 및 대체 방법
✅ 개선할 점
- 1차원 배열로 공간 최적화 가능
dp[0][j]
,dp[1][j]
값만 필요하므로, 크기를dp[2][3]
로 줄일 수 있다.dp[0] = {prev1, prev2, cur}
형태로 저장하면 공간을 절약할 수 있다.
- 입력과 동시에 DP 계산 가능
- 별도의
dp[][]
배열을 만들지 않고,sticker[][]
를 직접 수정하면서 DP 연산을 수행하면 메모리를 절약할 수 있다.
- 별도의
🔄 대체 방법
- 배열 없이 변수만으로 DP 연산 가능
prev2, prev1, cur
변수를 사용하면O(1)
공간 복잡도로 최적화 가능하다.
- 탑다운(Top-Down) 방식의 재귀 + 메모이제이션
- 현재 코드보다 더 복잡해지지만, 문제의 특성상 가능하다.
6. 결론
이 문제는 DP(다이나믹 프로그래밍)를 활용하여 최적의 스티커 선택을 찾는 문제이다.
💡 핵심은 이전 선택지와의 관계를 파악하고, 점화식을 적용하여 최댓값을 갱신하는 것!
DP 문제 유형을 연습하기에 적합하며, 공간 최적화 기법을 고민해볼 수도 있는 문제다. 🚀
'코딩테스트 > 백준' 카테고리의 다른 글
[백준] 7576번 - 토마토 문제 풀이 및 코드 해석 (Java) (1) | 2025.02.28 |
---|---|
[백준] 11286번 - 절댓값 힙 풀이 및 코드 분석 (Java) (0) | 2025.02.27 |
[백준] 7562번 - 나이트의 이동 풀이 및 코드 분석 (Java) (0) | 2025.02.27 |
[백준] 1992번 - 쿼드트리 풀이 및 코드 분석 (Java) (0) | 2025.02.27 |
[백준] 17471번 - 게리맨더링 풀이 및 코드 분석 (Java) (0) | 2025.02.27 |