[Gold IV] 가장 긴 증가하는 부분 수열 4 - 14002

JYC·2024년 3월 31일

[BAEKJOON]

목록 보기
60/102

문제 링크

성능 요약

메모리: 17332 KB, 시간: 176 ms

분류

다이나믹 프로그래밍

제출 일자

2024년 3월 31일 21:24:55

문제 설명

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.

입력

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.

둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000)

출력

첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.

둘째 줄에는 가장 긴 증가하는 부분 수열을 출력한다. 그러한 수열이 여러가지인 경우 아무거나 출력한다.

코드 (DP 풀이)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;

public class Main {
	static int[] arr; //숫자 배열
	static int[] dp; //가장 긴 증가하는 부분 수열 길이 배열
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		StringBuilder sb= new StringBuilder();
		
		int N = Integer.parseInt(br.readLine());
		st=new StringTokenizer(br.readLine());
		
		arr= new int[N+1];
		dp= new int[N+1];
		
		for(int i=0; i<N; i++) { //값 입력
			arr[i]=Integer.parseInt(st.nextToken());
			dp[i]=1; //길이 1로 설정
		}
		
		if(N==1) { //수열의 길이가 1이면 계산 의미없다.
			sb.append(1+"\n"); //출력값들 StringBuilder에 append
			sb.append(arr[0]);
		}
		else {
			for(int i=1; i<N; i++) {
				for(int j=0; j<i; j++) {
					if(arr[i]>arr[j]) { //만약 수열이 증가하는 경우라면?
						dp[i]=Math.max(dp[i], dp[j]+1); //더 긴 길이 찾기
					}
				}
			}
			int result=-1; //가장 긴 길이 찾기용
			Vector<Integer> vec = new Vector<Integer>();
			for(int i=0; i<N; i++) { //가장 긴 길이 찾기
				result=Math.max(result, dp[i]);
			}
			
			sb.append(result+"\n"); //길이 StringBuilder에 append
			int len= result; //가장 긴 길이 복사
			
			for(int i=N-1; i>=0; i--) { //역순으로 부분 수열 값 찾기
				//길이가 같은 dp 찾고 그때 숫자 배열을 Vector에 저장 후 len -1로 부분 수열 찾아간다.
				if(dp[i]==len) {
					vec.add(arr[i]);
					len--;
				}
				if(len==0) {
					break;
				}
			}
			
			for(int i=vec.size()-1; i>=0; i--) {
				sb.append(vec.get(i)+" "); //부분 수열들 StringBuilder에 append
			}
		}
		System.out.println(sb.toString());
	}
}

문제 풀이 순서
1. N 입력 받기.
2. 값 입력 받기 + dp 1로 초기화
3. 이중 for문으로 수열이 증가하는 형태인지 확인 후 더 긴 길이를 찾아나간다.
4. 가장 긴 길이를 result 변수에 저장하고 StringBuilder에 append해준다.
5. for문을 역순으로 가장 긴 길이의 부분 수열값들을 Vector에 add한다.
6. 각각의 부분 수열들을 StringBuilder에 append해준다.
7. StringBuilder 출력하기.

[비슷한 풀이 + 더 디테일한 설명] 더 디테일하게 설명한 블로그가 있어 참고용으로 올린다.

profile
열심히 하기 1일차

0개의 댓글