https://www.acmicpc.net/problem/2631
#include <iostream>
#include <vector>
#include <algorithm>
#define MAX 987654321
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n;
cin >> n;
vector<int> arr(n);
//dp[i]: i번째 사람 까지의 LIS
vector<int> dp(n, 0);
for (auto &item: arr) {
cin >> item;
}
for (int i = 0; i < n; i++) {
dp[i] = 1;
for (int j = 0; j < i; j++) {
if (arr[j] < arr[i]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
int ans = 0;
for (const auto &item: dp) {
ans = max(ans, item);
}
cout << n - ans;
return 0;
}
1. 문제
N명의 아이들이 임의의 순서로 줄을 서 있을 때, 번호 순서대로 배치하기 위해 옮겨지는 아이의 최소 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에는 아이들의 수 N이 주어진다. 둘째 줄부터는 1부터 N까지의 숫자가 한 줄에 하나씩 주어진다. N은 2 이상 200 이하의 정수이다.
출력
첫째 줄에는 번호 순서대로 줄을 세우는데 옮겨지는 아이들의 최소 수를 출력한다.
2. 풀이

예제를 풀이하는 방법이다. 이동시킬 아이들의 수는 이미 순서대로 서 있는 아이들을 고정시키고 그렇지 않은 아이들의 위치를 이동시키는 것이 최솟값이다. 밑줄 친 증가 부분수열을 고정시켜두고, 적절하지 않은 자리에 있는 아이를 옮겨준다. 즉, 최장 증가 부분수열(LIS)를 구해 총 아이 수에서 빼주면 된다.
for (int i = 0; i < n; i++) {
dp[i] = 1;
for (int j = 0; j < i; j++) {
if (arr[j] < arr[i]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
- dp[i]: i번째 아이까지의 LIS
j번째 아이보다 i번째 아이의 키가 더 크다면 j번째 아이->i번째 아이로 증가 부분수열을 만들 수 있다. 최장 수열을 구하는 것이므로 i보다 앞에 있는 각 아이들에 대해 수열의 길이를 갱신해준다.
int ans = 0;
for (const auto &item: dp) {
ans = max(ans, item);
}
cout << n - ans;
전체 dp 중 최댓값을 구한다. dp의 인덱스가 높다고 반드시 그 길이가 길진 않으므로 모든 dp에 대해 구해주어야 한다. 이 문제의 목표는 아이를 옮기는 최소 수를 구하는 것이므로 LIS의 길이를 전체 학생 수에서 빼준다.
'Coding Test' 카테고리의 다른 글
백준 2073 수도배관공 (C++) (1) | 2024.09.22 |
---|---|
백준 2758 로또 (C++) (1) | 2024.09.11 |
백준 18427 함께 블록 쌓기 (C++) (0) | 2024.09.06 |
백준 12904 A와 B (C++) (0) | 2024.09.03 |
백준 1790 수 이어 쓰기 2 (C++) (3) | 2024.08.31 |