https://www.acmicpc.net/problem/7570
목적
맨 앞이나 맨 뒤로 이동시키는 어린이의 수를 최소로하여 n명의 어린이를 번호 순으로 줄 세우자.
접근법
1. 최적의 선택으로 어린이를 맨 앞이나 맨 뒤로 이동시키게 되면, 일련의 연속된 순서로 정렬이 되어야 할 것이다. 정렬 과정을 거꾸로 보자.
- 6명의 어린이가 있고 1명의 어린이만 맨 뒤로 보내면 되는 상황이다. 6번 어린이를 맨 뒤로 보냄으로써 1에서 5까지 연속된 배열의 길이가 1 증가하여 정렬이 마무리 된다.
- 이전 상황으로 1에서 4까지 일련의 연속된 배열이 있다. 이 배열의 길이를 증가시키기 위해선 2명의 어린이를 앞 또는 뒤로 이동시켜야 하고 5가 이동하여 1~5의 배열을 형성하게 된다.
- 한번 더 이전으로 가면 2에서 4까지의 연속된 배열을 볼 수 있다. 이 배열의 길이를 증가시키기 위해선 3명의 어린이를 이동시켜야하며 1번 어린이와 5번 어린이를 이동시킬 수 있다.
2. 바로 위의 상황에서 2,3,4,6을 이동시키지 않고 5나 1을 이동시킨 이유를 생각해보자. 어린이를 한번 이동시키면 1에서 6까지의 부분 배열의 길이를 1씩 증가시켜야 최소한의 이동으로 정렬을 할 수 있다. 즉, 가장 긴 연속된 배열의 길이를 증가시켜 나가야 최소한의 이동을 하게 되는 것이다.
3. 한번 이동으로 해당 배열의 길이가 1씩 증가하므로, 최소로 이동시켜야 하는 어린이의 수는 가장 긴 연속된 배열의 길이에서 어린이의 수를 빼면 된다.
4. 따라서 연속된 LIS를 구해야 하며, dp로 해결한다. p[i]는 i번 학생으로 끝나는 배열의 길이로, i-1번 학생으로 끝나는 배열의 길이(p[i-1])에서 1을 더한 값이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#include<bits/stdc++.h>
#define f(i,l,r) for(int i=l;i<r;++i)
using namespace std;
int n,no,mx,p[(int)1e6+1];
int main(){
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>n;
f(i,0,n){
cin>>no;
mx=max(mx,p[no]=p[no-1]+1);
}
cout<<n-mx;
return 0;
}
|
문제 설명과 코드에 대한 피드백은 언제나 환영합니다.
다양한 의견 댓글로 남겨주세요.
'Problem Solving > BOJ 백준' 카테고리의 다른 글
[ BOJ 백준 8983번 - 사냥꾼 ] 해설 및 코드 (0) | 2020.03.24 |
---|---|
[ BOJ 백준 10090번 - Counting Inversions ] 해설 및 코드 (0) | 2020.03.24 |
[ BOJ 백준 4013번 - ATM ] 해설 및 코드 (0) | 2020.03.22 |
[ BOJ 백준 2152번 - 여행 계획 세우기 ] 해설 및 코드 (0) | 2020.03.21 |
[ BOJ 백준 3977번 - 축구 전술 ] 해설 및 코드 (0) | 2020.03.20 |