https://www.acmicpc.net/problem/7570
7570번: 줄 세우기
입력은 2 개의 줄로 이루어져 있다. 첫 줄에는 어린이 수를 나타내는 정수가 주어진다. 둘째 줄에는 처음에 줄서있는 어린이들의 번호가 차례대로 주어진다. 주어진 번호들 사이에는 공백이 하
www.acmicpc.net
1차 시도
처음에 이걸 그리디로 해결하기 위해서 다음과 같이 생각했다.
1. 앞으로 옮겼을 때, 뒤쪽에 자신보다 큰 수들이 많이 위치하는 것을 골라야한다.
2. 뒤로 옮겼을 때, 앞쪽에 자신보다 큰 수들이 많이 위치하는 것을 골라야 한다.
그러나 이것은 금방 틀리다는 것을 알 수 있다.
가령 1,2번이 맞다고 하더라도 순서대로 이어져있지 않으면 문제가 된다.
따라서, 순서를 집중해서 공략하는게 좋겠다고 생각했다.
순서대로인 부분수열 중 가장 긴 것을 골라야, 부분수열이 아닌 나머지 수가 가장 최소가 되므로
가장 긴 부분수열 중 순서대로 인 것을 찾아야 함을 알게 되었다.
이를 구현하기 위해서 DP를 이용하였다.
예전에 풀었던 가장 긴 증가하는 부분수열을 이용하여 구현하였는데 틀렸다.
[👊DP뿌시기 #7] (BOJ 11053) 가장 긴 증가하는 부분 수열
https://www.acmicpc.net/problem/11053 11053번: 가장 긴 증가하는 부분 수열 수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인
meteorfish.blog
O(N^2)로 풀게되면 시간초과가 나게된다...
이를 어떻게 하면 시간복잡도를 줄일 수 있을까 고민했다.
2차 시도
질문 게시판을 참고하였다..
굳이 i보다 이전들을 파해치며, 가장 큰 dp를 구할 필요가 없다.
dp를 0으로 초기화 한 후, dp[i-1]이 0이 아니면 dp[i] = dp[i-1] + 1을 하면되고,
dp[i-1]이 0이면, dp[i] 를 1로 두면된다.
따라서, 위 알고리즘을 이용하여 O(N)에 해결할 수 있다.
코드
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
#define MAX 1000001
int n;
int arr[MAX];
int res = -1;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 0; i < n; i++) {
int tmp;
cin >> tmp;
// 이전이 없으면 1
if (arr[tmp - 1] == 0) {
arr[tmp] = 1;
}
else {
arr[tmp] = arr[tmp - 1] + 1;
res = max(res, arr[tmp]);
}
}
if (n != 1)
cout << n - res;
else
cout << 0;
}
'📊알고리즘 > BOJ' 카테고리의 다른 글
BOJ 1799 - 비숍 (🔄) (0) | 2024.02.29 |
---|---|
BOJ 16987 - 계란으로 계란치기 (0) | 2024.02.28 |
[그리디 #20] BOJ 2212 - 센서 (0) | 2024.02.25 |
[백트래킹 #1] BOJ 15649 - N과 M (1) (0) | 2024.02.23 |
[그리디 #19] BOJ 2812 - 크게 만들기 (1) | 2024.02.23 |