코드트리 | 코딩테스트 준비를 위한 알고리즘 정석
국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.
www.codetree.ai
꼭 n개를 뽑아야 한다 같은 유형의 dp를 푸는 방식을 사용했다.
이 문제에서는 n개의 카드 짝이 주어지고, 이 카드들 중 빨강, 파랑 을 정확히 n번 씩 사용했을 때 카드의 합의 최댓값을 구해야 한다.
위와 같이 주어졌다고 가정해보자. 위 4가지 카드 중 빨강, 파랑을 각각 2개씩 뽑아야 한다.
이를 풀기 위해 dp배열을 만들었다. 이 배열에서 i는 현재 탐색중인 카드 짝의 번호를 의미하고, j는 현재 뽑은 카드 중 빨강색의 갯수를 의미한다.
이 문제에서는 모든 값이 양수라서 dp에 최솟값을 따로 넣을 필요가 없지만, 만약 음수도 입력된다면 최솟값을 꼭 모든 값에 입력해야한다.
dp[0][0]는 아무 카드도 뽑지 않는 경우이므로 0을 넣었다.
dp를 채울 때에는 위와 같이 두 가지 상황을 고려해야 한다.
보라색은 빨간 카드를 쓰는 경우의 수가 하나 증가했으니, 빨간 카드를 정한 것을 의미한다.
초록색은 빨간 카드를 쓰는 경우의 수가 증가하지 않았으니 파란 카드를 정한 것을 의미한다. 이 때 dp값은 최댓값을 구해야하므로 위 두 경우 중 더 큰 값을 넣으면 된다.
여기서 예외처리를 해야 하는 부분이 있는데,
- j값이 0이라서 빨간색 카드를 사용할 수 없는 경우
- 이제까지 탐색한 카드의 수가 j와 같을 때 ( 그럼 이전 짝에서 고른 카드의 수가 j보다 많았다는 모순이 발생하므로)
이를 잘 고려해서 dp를 채우고, 다 채운 배열에서 제일 오른쪽 하단의 값이 모든 카드를 탐색했고, 빨간색의 수가 n개인 경우중 최댓값이므로 답이 된다.
import java.io.*;
import java.util.*;
import java.math.*;
public class Main {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
StringTokenizer st;
int[] a = new int[n*2+1];
int[] b = new int[n*2+1];
for(int i = 1;i<=2*n;i++){
st = new StringTokenizer(br.readLine());
a[i] = Integer.parseInt(st.nextToken());
b[i] = Integer.parseInt(st.nextToken());
}
int[][] dp = new int[2*n+1][n+1];
dp[0][0] = 0;
for(int i = 1;i<=2*n;i++){
for(int j = 0;j<=n;j++){
if(j == 0) dp[i][j] = dp[i-1][j] + b[i]; // 빨간색을 0번 사용하는 경우
else if(j == i) dp[i][j] = dp[i-1][j-1] + a[i]; //현재 탐색하는 카드 수보다 i가 더 많을 때
else dp[i][j] = Math.max(dp[i-1][j-1] + a[i], dp[i-1][j] + b[i]);
}
}
System.out.println(dp[2*n][n]);
}
}
i == j일 때 의 경우를 고려하지 않아서 틀렸습니다가 나왔다.
'알고리즘 > 코드트리 문제풀이' 카테고리의 다른 글
코드트리 [자바 java] 정수 n개의 합 2 (0) | 2023.08.18 |
---|---|
코드트리 [자바 java] 최장 공통 부분 수열 (0) | 2023.08.17 |
코드트리 [자바 java] 적절한 옷 고르기 (0) | 2023.08.15 |
코드트리 [자바 java] 연속 부분 합의 최댓값 구하기 (0) | 2023.08.14 |
코드트리 [자바 java] 동전 거슬러주기 (0) | 2023.08.13 |