문제 링크
- http://icpc.me/5813
문제 출처
- 2012 IOI Day2 1번
사용 알고리즘
- DFS
풀이
4번째로 쓰는 ioi문제 풀이입니다.
문제에 주어진 조건을 보면 블록이 있는 칸끼리 서로 연결되어 있고, 그렇지 않은 칸끼리도 서로 연결되어 있습니다.
이 말은 블록이 있는 칸 사이에는 경로가 항상 존재하고, 블록이 없는 칸 사이에도 항상 경로가 존재합니다.
문제를 아래와 같이 총 4단계로 나누어 풀어보겠습니다.
- 문제가 1차원이라면?
- 트리의 모든 정점 사이의 거리의 합
- subtask3
- 전체 문제
문제가 1차원이라면?
문제를 2차원이 아닌 1차원이라고 생각해봅시다.
블록이 있는 칸은 모두 연결이 되어있으므로 선분 하나만 존재할 것입니다. 이런 경우에는 (i < j)인 모든 |xi - xj|의 합을 O(n log n)만에 정렬 후 O(n)에 구할 수 있습니다.
트리의 모든 정점 사이의 거리의 합
이번에는 트리에서 모든 정점 사이의 거리의 합을 구하는 방법을 생각해봅시다. 아래 코드를 통해 쉽게 구할 수 있습니다.
1 |
|
subtask3
섭테3은 아래 조건을 만족합니다.
- X[i] = X[j]인 임의의 두 비어있지 않은 셀들이 주어질 때, 그들 사이의 모든 셀들 또한 비어있지 않다.
- Y[i] = Y[j]인 임의의 두 비어있지 않은 셀들이 주어질 때, 그들 사이의 모든 셀들 또한 비어있지 않다.
이 조건을 만족하면 각 셀 사이의 이동 거리는 무조건 |xi - xj| + |yi - yj|입니다.
블록들을 행 별로 분리해서 x 좌표의 거리를 구하고, 열 별로 분리해서 y 좌표의 거리를 구하면 답을 구할 수 있습니다.
전체 문제
블록이 있는 셀들을 행 단위로 잘라내어봅시다.
붙어있는 셀들(덩어리)을 하나의 정점으로 만들고, 인접한 덩어리끼리 간선으로 이어주면 아래 그림과 같이 그래프가 만들어집니다.
만들어지는 그래프는 문제의 조건에 의해 사이클이 없고, 모든 정점이 연결되어 있으므로 트리가 됩니다.
위 사진에 있는 트리에서 정점들 사이의 거리는 y축으로 평행하게 이동하는 거리와 동일합니다. 그러므로 트리의 정점들 사이의 거리의 합을 구하면 y 변화량을 구할 수 있습니다.
x좌표와 y좌표를 바꾸어서 적절히 처리를 해준다면 x변화량도 구할 수 있습니다.
전체 코드
1 |
|