문제 링크
- http://icpc.me/15974
문제 출처
- 2018 KOI 중등부 4번
사용 알고리즘
- DP
- sliding window
시간복잡도
- $O(N^2 log N)$
풀이
2018년 문제는 BOJ에서 서브태스크를 지원해주길래, 서브태스크를 따라서 풀어봤습니다.
Subtask 1(14점)
모든 점이 발자국에 포함됩니다. 발뒤꿈치를 잡고, 각도 순으로 정렬해주면 됩니다.
코드
Subtask 2(26점)
모든 경우의 수를 $O(2^N N^3)$ 정도의 시간으로 확인해볼 수 있습니다. 계속 답이 안 나오길래 막 짜다보니 코드가 조금 더러워졌습니다…
코드
Subtask 3(55점)
이제부터 점점 100점 풀이에 다가가기 시작합니다.
$DP(0, i, j)$ = 마지막으로 선택한 점이 j, 마지막에서 두 번째로 선택한 점이 i이면서 j가 발가락인 경우
$DP(1, i, j)$ = j가 골인 경우처럼 dp를 잘 정의하고 문제를 풀어봅시다.
$DP(0, i, j)$은 적당한 k들에 대해 $max(dp(1, k, i)) + 1$이고, DP(1, i, j)도 적당한 k들에 대해 $max(dp(0, k, i)) + 1$입니다.
각 상태마다 적당한 k들에 대해 모두 탐색을 해준다면 $O(N^3)$에 정답을 구할 수 있습니다. 답을 역추적하기 위해서 $DP(*, i, j)$가 최대가 되는 k도 같이 저장해야 합니다.
코드
Subtask 4(100점)
Subtask 3에서의 풀이를 $O(N^2)$ 혹은 $O(N^2 log N)$ 정도로 최적화해야합니다.
$DP(t, k, i)$를 모두 계산해놓은 상태에서 $DP(1-t, i, j)$를 계산하는 방식으로 dp table을 채울 것입니다.
발뒷꿈치를 기준으로 각도 순으로 정렬한 상황에서, k는 i보다 먼저 나오고, j는 i보다 나중에 나옵니다. i를 기준으로 먼저 나오는 점들과 나중에 나오는 점들을 각각 나눠서 점 i를 기준으로 정렬합시다.
$DP(1-t, i, j) = max(DP(t, k, i)) + 1$를 그대로 이용할건데, 각 j에 대해 $DP(1-t, i, j)$가 최대가 되는 k는 슬라이딩 윈도우를 통해 구해줄 수 있습니다.
각 i마다 $O(N log N)$에 처리할 수 있기 때문에 총 시간복잡도는 $O(N^2 log N)$입니다.
전체 코드
1 |
|