메모리: 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의 가장 긴 증가하는 부분 수열의 길이를 출력한다.
둘째 줄에는 가장 긴 증가하는 부분 수열을 출력한다. 그러한 수열이 여러가지인 경우 아무거나 출력한다.
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 출력하기.
[비슷한 풀이 + 더 디테일한 설명] 더 디테일하게 설명한 블로그가 있어 참고용으로 올린다.