본문 바로가기
OLD_알고리즘/Baekjoon

백준] 11054 : 가장 긴 바이토닉 부분 수열

by 달승 2020. 9. 24.

BOJ에서 다음 문제들을 쭉 순서대로 풀어본다.  boj.kr/문제번호 <= 형태로 검색하면 된다.

DP - 1463, 11726, 11727, 9095, 10844, 11057, 2193, 9465, 2156, 11053, 11055, 11722, 11054, 1912, 2579, 1699, 2133, 9461, 2225, 2011, 11052

 

 

1시간 넘어가면 풀던 짓을 그만두고 반드시 AC받은 코드 찾아보기 (설명이 꼭 달려있는 코드를 읽자)

그리고 푼 다음에는 반드시 다른 사람의 코드를 봐야 한다.

특히 자신만의 가상의 스승을 잡고 그 분의 코드를 보는 것도 좋은 방법이라 생각한다.

너무 갓갓들은 이상한 방식으로도 짜는 경우도 있기 때문에 적당한 사람을 선택해야 한다.

 

 

알고리즘 문제풀이(PS) 시작하기

plzrun.tistory.com

 

내가 애용하는 IDE 사이트

(IDE 자동 완성이 불가능하기 때문에 사용하는 중)

 

Ideone.com

ideone.com


 

 

11054번: 가장 긴 바이토닉 부분 수열

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

www.acmicpc.net

 

 

문제  : 

수열 S가 어떤 수 Sk를 기준으로 S1 < S2 < ... Sk-1 < Sk > Sk+1 > ... SN-1 > SN을 만족한다면, 그 수열을 바이토닉 수열이라고 한다.

예를 들어, {10, 20, 30, 25, 20}과 {10, 20, 30, 40}, {50, 40, 25, 10} 은 바이토닉 수열이지만,  {1, 2, 3, 2, 1, 2, 3, 2, 1}과 {10, 20, 30, 40, 20, 30} 은 바이토닉 수열이 아니다.

수열 A가 주어졌을 때, 그 수열의 부분 수열 중 바이토닉 수열이면서 가장 긴 수열의 길이를 구하는 프로그램을 작성하시오.

 

입력  : 

첫째 줄에 수열 A의 크기 N이 주어지고,

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

 

출력  : 

첫째 줄에 수열 A의 부분 수열 중에서 가장 긴 바이토닉 수열의 길이를 출력한다.

 

>>> 예제의 경우 {1 5 2 1 4 3 4 5 2 1}이 가장 긴 바이토닉 부분 수열이다.

 

 

 

 

접근 방법

 

 

...

더보기

첫 번째 코드 : 틀림

 

-> 이유는 StartDP랑 EndDP랑 각각 max값 구해서 더하고 -1을 해줬기 때문

 

#include <iostream>
using namespace std;

int dpStart[1001], dpEnd[1001], arr[1001];

int main() {
	int n, maxStart = 0, maxEnd = 0;
	
	cin >> n;
	
	for(int i = 0; i < n; i++){
		cin >> arr[i];
	}
	
	for(int i = 0; i < n; i++){
		
		dpStart[i] = 1;

		for(int j = 0; j < i; j++){
			
			if(arr[j] < arr[i] && dpStart[i] <= dpStart[j]){
				dpStart[i] = dpStart[j] + 1;
			}
		}
		//cout << dpStart[i] << " ";
		
		if(maxStart < dpStart[i]){
			maxStart = dpStart[i];
		}
	}
	
		for(int i = n - 1; i >= 0; i--){
			dpEnd[i] = 1;

		for(int j = n - 1; j > i; j--){
			
			if(arr[j] > arr[i] && dpEnd[i] >= dpEnd[j]){
				dpEnd[i] = dpEnd[j] + 1;
			}
		}
		//cout << dpEnd[i] << " ";
		if(maxEnd < dpEnd[i]){
			maxEnd = dpEnd[i];
		}
	}
	
	cout << (maxStart + maxEnd) - 1; 
	
	return 0;
}

 

 

 

 

두 번째 코드 : 주석 부분이 틀린 곳임.

 

#include <iostream>
using namespace std;

int dpStart[1001], dpEnd[1001], arr[1001];

int main() {
	int n, max = 0;
	
	cin >> n;
	
	for(int i = 0; i < n; i++){
		cin >> arr[i];
	}
	
	for(int i = 0; i < n; i++){
		
		dpStart[i] = 1;

		for(int j = 0; j < i; j++){
			
			if(arr[j] < arr[i] && dpStart[i] <= dpStart[j]){
				dpStart[i] = dpStart[j] + 1;
			}
		}

		//if(maxStart < dpStart[i]){
		//	maxStart = dpStart[i];
		//}
	}
	
		for(int i = n - 1; i >= 0; i--){
			dpEnd[i] = 1;

		for(int j = n - 1; j >= i; j--){
			
//			if(arr[j] > arr[i] && dpEnd[i] >= dpEnd[j]){
			if(arr[j] < arr[i] && dpEnd[i] <= dpEnd[j]){

				dpEnd[i] = dpEnd[j] + 1;
			}
		}
		//if(maxEnd < dpEnd[i]){
		//	maxEnd = dpEnd[i];
		//}
	}
	
	//cout << (maxStart + maxEnd) - 1; 
	for(int i = 0; i < n; i++){
		if(max < dpEnd[i] + dpStart[i] - 1){
			max = dpEnd[i] + dpStart[i] - 1;
		}
	}
	
	cout << max;
	
	return 0;
}

 

 

 

정답 코드

#include <iostream>
using namespace std;

int dpStart[1001], dpEnd[1001], arr[1001];

int main() {
	int n, max = 0;
	
	cin >> n;
	
	for(int i = 0; i < n; i++){
		cin >> arr[i];
	}
	
	for(int i = 0; i < n; i++){	
		dpStart[i] = 1;

		for(int j = 0; j < i; j++){	
			if(arr[j] < arr[i] && dpStart[i] <= dpStart[j]){
				dpStart[i] = dpStart[j] + 1;
			}
		}
	}
	
		for(int i = n - 1; i >= 0; i--){
			dpEnd[i] = 1;

		for(int j = n - 1; j >= i; j--){
			if(arr[j] < arr[i] && dpEnd[i] <= dpEnd[j]){
				dpEnd[i] = dpEnd[j] + 1;
			}
		}
	}
	
	for(int i = 0; i < n; i++){
		if(max < dpEnd[i] + dpStart[i] - 1){
			max = dpEnd[i] + dpStart[i] - 1;
		}
	}
	
	cout << max;
	
	return 0;
}

 

 

 

 

참고한 블로그

 

[백준] 11054 - 가장 긴 바이토닉 부분 수열

문제 링크 : https://www.acmicpc.net/problem/11054이 문제를 풀어 보기 전에 LIS문제들을 풀어보는 것...

blog.naver.com

 

댓글