알고리즘
[백준] DP - 11722번, 가장 긴 감소하는 부분 수열
hatch
2023. 10. 18. 00:39
728x90
반응형
* 공부 목표
DP - 1463, 11726, 11727, 9095, 10844, 11057, 2193, 9465, 2156, 11053, 11055, 11722, 11054, 1912, 2579, 1699, 2133, 9461, 2225, 2011, 11052
문) 수열 A가 주어졌을 때, 가장 긴 감소하는 부분 수열을 구하는 프로그램을 작성하시오.
예를 들어, 수열 A = {10, 30, 10, 20, 20, 10} 인 경우에 가장 긴 감소하는 부분 수열은 A = {10, 30, 10, 20, 20, 10} 이고, 길이는 3이다.
출) 첫째 줄에 수열 A의 가장 긴 감소하는 부분 수열의 길이를 출력한다.
풀이
1. 테이블 정의 : n만큼의 길이의 수열을 입력받고 각각을 비교하여 부분 수열의 길이를 출력
2. 점화식 : dp[i] = dp[j] + 1;
3. 초기값 : dp[i] = 1;
지난 풀이와 비슷하다. 현재 값과 이전 값들을 하나하나 비교하면서 감소 수열을 찾는 것이다.
다만 신경써야하는 건 감소 순열이기 때문에 다음의 조건을 만족해야 한다.
- 이전 값들이 현재 값보다 커야 한다(arr[j] > arr[i]).
- 현재 누적 값(dp[i] = 1)보다 이전 누적값+1이 더 커야한다.
- 동일 값일 경우 누적값은 같다.
왜 누적값에 대한 조건을 넣어야하는가?
(반례) 4 / 6 5 7 3 (정답) 3 (출력) 2
테스트케이스 | 6 | 5 | 7 | 3 |
출력 | 1 | 2 | 1 | 2 |
정답 | 1 | 2 | 1 | 3 |
코드
Scanner + System.out.println();
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
int[] dp = new int[n];
for(int i=0; i<n; i++) {
arr[i] = sc.nextInt();
}
for(int i=0; i<arr.length; i++) {
dp[i] = 1;
for(int j=0; j<i; j++) {
if(arr[j]>arr[i] && dp[i] < dp[j]+1) {
dp[i] = dp[j] + 1;
} else if (arr[i] == arr[j]) {
dp[i] = dp[j];
}
}
}
int max = 0;
for(int i=0; i<dp.length; i++) {
max = dp[i]>max?dp[i]:max;
}
sc.close();
System.out.println(max);
}
}
BufferedReader + System.out.println();
import java.io.*;
import java.util.*;
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());
int[] arr = new int[n];
int[] dp = new int[n];
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
for(int i=0; i<n; i++) {
if(st.hasMoreTokens()) {
arr[i] = Integer.parseInt(st.nextToken());
}
}
for(int i=0; i<arr.length; i++) {
dp[i] = 1;
for(int j=0; j<i; j++) {
if(arr[j]>arr[i] && dp[i] < dp[j]+1) {
dp[i] = dp[j] + 1;
} else if (arr[i] == arr[j]) {
dp[i] = dp[j];
}
}
}
int max = 0;
for(int i=0; i<dp.length; i++) {
max = dp[i]>max?dp[i]:max;
}
br.close();
System.out.println(max);
}
}

코드 길이는 주석을 추가하면서 좀 차이가 나게 됐다.
최적화를 위해서는 Scanner보다 BufferedReader를 사용하는 편이 훨씬 좋겠다.